could you please briefly expand on how the change from declaring the variables with my to our affects this scenario?
Briefly? Code blocks in regexp patterns capture lexical variabless when they are compiled, just like anonymous subs. Package variables aren't captured. In case that didn't do the trick, the longer answer follows.
Code blocks in regexps are anonymous subs.
sub f {
my ($x) = @_;
'' =~ /(?{ print "$x\n" })/;
}
f(4); # 4
f(5); # 4!!
effectively does
sub f {
my ($x) = @_;
$block ||= sub { print "$x\n" };
$block->();
}
f(4); # 4
f(5); # 4!!
The $x from the first pass is captured when the sub is compiled. It's a very powerful feature which allows the simplification of many problems. For example,
BEGIN {
package Prefixer;
sub new {
my ($class, $prefix) = @_;
return bless({ prefix => $prefix }, $class);
}
sub prefix {
my ($self) = @_;
return join '', $self->{prefix}, @_;
}
}
my $a_prefixer = Prefixer->new('a');
my $b_prefixer = Prefixer->new('b');
print("$_\n")
for $a_prefixer->prefix('1'), # a1
$a_prefixer->prefix('2'), # a2
$b_prefixer->prefix('3'), # b3
$b_prefixer->prefix('4'); # b4
can be simplified to
sub make_prefixer {
my ($prefix) = @_;
return sub { return join '', $prefix, @_ };
}
my $a_prefixer = make_prefixer('a');
my $b_prefixer = make_prefixer('b');
print("$_\n")
for $a_prefixer->('1'), # a1
$a_prefixer->('2'), # a2
$b_prefixer->('3'), # b3
$b_prefixer->('4'); # b4
However, subs only capture lexical variables, not package variables. By using package variables, the problem goes away.
sub f {
local our ($x) = @_;
$block ||= sub { print "$x\n" };
$block->();
}
f(4); # 4
f(5); # 5
sub f {
local our ($x) = @_;
'' =~ /(?{ print "$x\n" })/;
}
f(4); # 4
f(5); # 5
|