Others have already pointed out the issue with nested sub
s, but here is my answer to my understanding of your question:
The "scope" of a my
declaration begins after the statement that contains the my
, not at the beginning of the block it occurs in. Otherwise, both of these would work:
$ perl -wMstrict -le 'sub foo { my $bar="quz"; print $bar; } foo()'
quz
$ perl -wMstrict -le 'sub foo { print $bar; my $bar="quz"; } foo()'
Global symbol "$bar" requires explicit package name (did you forget to declare "my $bar"?) at -e line 1.
Execution of -e aborted due to compilation errors.
Also, note the following:
my $x = 3;
{
my $x = $x + 5;
print "1: $x\n"; # prints "1: 8"
}
print "2: $x\n"; # prints "2: 3"
In your first piece of code, at the point you declare sub b
, Perl only knows about the global $x = 8
, so that's what print "B: $x\n"
is using. In the second piece of code, Perl has seen my $x = 3
, so that's what it uses. This effect also occurs if you don't use nested sub
s:
my $x = 8;
sub a {
my $subb = sub {
print "B: $x\n";
};
my $x = 3;
$subb->();
}
a(); # prints "B: 8"
and
my $x = 8;
sub a {
my $x = 3;
my $subb = sub {
print "B: $x\n";
};
$subb->();
}
a(); # prints "B: 3"