in reply to How do closures and variable scope (my,our,local) interact in perl?
Declaring a variable with our effectively creates a package variable (i.e. a typeglob entry) and bequeaths a lexical scope upon the short name symbol. A for() loop aliases it's loop variable, so that our $name loop-variable behaves like a local. That's why declaring $name with our results in $name being undefined after the for() loop run, hence the generated subroutines output an empty $name.
Why does the my-variable version work as expected? - Because the for() loop aliases the my variable as - a my variable. Now, for those the compiler inserts an opcode which clears it after (or before?) every iteration (on ENTER or LEAVE), so that you have a brand new $name (with its own private storage!) each time through the loop.
If you close over a localized our() variable, as per your example, all your generated subs share the same local, which isn't visible outside.
Perl is trying really hard to dwim here, and imho does a good job ;-)
update:
Actually, there's more to it, since the loop variable gets an alias of the list it iterates over. Consider:
my $name; for $name (qw(red blue green yellow orange purple violet)) { no strict 'refs'; # allow symbol table manipulation no warnings 'redefine'; #ignore noise about redefinitions *$name = sub { my $sOutput = "<FONT COLOR='$name'>@_</FONT>"; $name = 'something wacky and wonderful'; #change the value return $sOutput; }; } print "red: ${\(red())}\n"; __END__ Modification of a read-only value attempted at - line 7.
Here the for() iterates over a list of literals, and those are read-only. But! ...
our $name; for $name (qw(red blue green yellow orange purple violet)) { no strict 'refs'; # allow symbol table manipulation no warnings 'redefine'; #ignore noise about redefinitions *$name = sub { my $sOutput = "<FONT COLOR='$name'>@_</FONT>"; $name = 'something wacky and wonderful'; #change the value return $sOutput; }; } print "red: ${\(red())}\n"; __END__ red: <FONT COLOR=''></FONT>
...why? In this case, the sub closes over the localized $name, which is undefined after the loop finished. That's why you get
----- sub used inside loop that defined it ------ trying out something wacky and wonderful: <FONT COLOR='something wacky + and wonderful'></FONT>
inside the last loop - you had modified $colors[0] in the previous loop.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: How do closures and variable scope (my,our,local) interact in perl?
by ELISHEVA (Prior) on Jun 16, 2009 at 17:09 UTC | |
by ikegami (Patriarch) on Jun 16, 2009 at 17:57 UTC | |
by ELISHEVA (Prior) on Jun 16, 2009 at 19:02 UTC | |
by ikegami (Patriarch) on Jun 16, 2009 at 19:43 UTC | |
by shmem (Chancellor) on Jun 16, 2009 at 21:29 UTC | |
by ikegami (Patriarch) on Jun 16, 2009 at 20:03 UTC | |
by shmem (Chancellor) on Jun 16, 2009 at 17:56 UTC |