Your first two examples work because you are adding $_ and the first arg to the function. The for loop you use to print $fs[$_] binds $_, and your anonymous function uses that value. The result is something that appears to work. If you change the loop variable to something else, though, $_ will be unbound, and you will be adding to an undefined value. ("use warnings" will whine about this.)
If you then create functions that add $i and the argument, your loop stops working, because the loop binds $_ instead of $i.
Basically, you need some "my" keywords in there before your example becomes meaningful in any way. "use strict" and "use warnings" are your friend. ("use strict" will whine about the 'for $i (...)' construct that should be 'for my $i (...)', and "use warnings" will whine about $i being undefined when you try to evaluate one of the created functions.)
One last thing, if you were experimenting in Devel::REPL (re.pl), you would have noticed this problem much sooner. strict and warnings are on by default, which would have produced errors and warnings for all of your examples. It also dumps the result of evaluation with Data::Dump::Streamer, so you can actually see what's being closed over. Examples:
> my @fs = map { sub { $_ + $_[0] } } 1..2
$ARRAY1 = [
sub {
package Devel::REPL::Plugin::Packages::DefaultScratchpad;
use warnings;
use strict 'refs';
$_ + $_[0];
},
'V: $ARRAY1->[0]'
];
$ARRAY1->[1] = $ARRAY1->[0];
DDS shows you the code, and it is even smart enough to know that the two functions you produced are identical.If we do it "right":
> my @fs = map { my $i = $_; sub { $i + $_[0] } } 1..2
my ($i,$i_eclipse_1);
$i = 1;
$i_eclipse_1 = 2;
$ARRAY1 = [
sub {
package Devel::REPL::Plugin::Packages::DefaultScratchpad;
use warnings;
use strict 'refs';
$i + $_[0];
},
sub {
package Devel::REPL::Plugin::Packages::DefaultScratchpad;
use warnings;
use strict 'refs';
$i_eclipse_1 + $_[0];
}
];
You can see that the two functions are different, and that they don't share the same $i.I'm convinced and will try Devel::REPL, instead of "traditional" one-liners.
Here's one variation..... http://www.perlmonks.org/?node_id=719475