I have a strange behaved (to Python programmer) subroutine, which simplified as the following:
use strict;
use Data::Dumper;
sub a {
my @x;
sub b { push @x, 1; print "inside: ", Dumper(\@x); }
&b;
print "outside: ", Dumper(\@x);
}
&a;
&a;
I found the result is:
inside: $VAR1=[ 1 ]
outside: $VAR1 = [ 1 ]
inside: $VAR1=[1, 1]
outside: $VAR1= []
What I thought is when calling &a
, @x
is empty array after "my @x
" and has one element after "&b
", then dead. Every time I call &a
, it is the same. so the output should be all $VAR1 = [ 1 ]
.
Then I read something like named sub routine are defined once in symbol table, then I do "my $b = sub { ... }; &$b;
", it seems make sense to me.
How to explain?
As per the "perlref" man page:
named subroutines are created at compile time so their lexical variables [i.e., their 'my' variables] get assigned to the parent lexicals from the first execution of the parent block. If a parent scope is entered a second time, its lexicals are created again, while the nested subs still reference the old ones.
In other words, a named subroutine (your b
), has its @x
bound to the parent subroutine's "first" @x
, so when a
is called the first time, b
adds a 1
to @x
, and both the inner and outer copies refer to this same version. However, the second time a
is called, a new @x
lexical is created, but b
still points to the old one, so it adds a second 1
to that list and prints it (inner), but when it comes time for a
to print its version, it prints out the (empty) brand new lexical (outer).
Anonymous subroutines don't exhibit this problem, so when you write my $b = sub { ... }
, the inner @x
always refers to the "current" version of a
's lexical @x
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With