http://www.perlmonks.org?node_id=719562


in reply to Re^4: Lexical closures
in thread Lexical closures

I think we can also show how the aliased variable can be global with the following,
use vars '$i'; $i = 123; sub foo { my $arg = shift; print "$arg, $i\n"; } foreach $i (0..2) { foo($i); } foo('x'); # obviously alias works only within the loop # Prints, # 0,0 # 1,1 # 2,2 # x,123
If so, I have a question related to my scope. Within the previous example let's declared $i with my instead.
my $i; $i = 123; sub foo { my $arg = shift; print "$arg, $i\n"; } foreach $i (0..2) { foo($i); } foo('x'); # Prints, # 0,123 # 1,123 # 2,123 # x,123

At this point I'm confused in fact. Should not we get the same result? Does not my scope to nested blocks as well?

It looks like aliasing does not affect my'd variable despite to be within the same scope or nested scope. The previous result is what I have expected using my on the foreach itself.

Replies are listed 'Best First'.
Re^6: Lexical closures
by ikegami (Patriarch) on Oct 25, 2008 at 22:33 UTC

    In the second snippet, foo() captures $i since $i is a lexical. That means the $i in foo() will always refer to the specific SV associated with $i when foo was compiled. When the loop aliases $i to a different SV, it doesn't affect foo.

    use Devel::Peek; my $i; # Lexical variable sub foo { Dump($i); } Dump($i); # SV ... at 0x226048 \ for $i ( 1 ) { # > same foo(); # SV ... at 0x226048 / Dump($i); # SV ... at 0x226d8c }

    In the first snippet, there is no closure since $i is not a lexical. That means the foo() will always grab the current value of $main::i.

    use Devel::Peek; our $i; # Package variable sub foo { Dump($i); } Dump($i); # SV ... at 0x226d94 for $i ( 1 ) { foo(); # SV ... at 0x226d7c \ same Dump($i); # SV ... at 0x226d7c / }