in reply to RE: RE (tilly) 1: for loops, closures
in thread for loops, closures

In case it isn't obvious, I am not guessing about why what you did worked and what the gotchas are. Consider the following code:
my @list = 1..8; my @ref_list; foreach my $i (@list) { push( @ref_list, sub { print " \$i == $i\n" } ); } foreach my $i (@list) { $i = "gone"; } print "for SCALAR LIST\n"; while ( $code_ref = pop @ref_list ) { &$code_ref; }
Do you see what happened there?

Nope. It was not an accident that your code worked. Perl worked exactly as documented.

But if you code that way without understanding why it works, then you will get bitten eventually. I am saying that because I have been there, done that, and bear the scars. Else I wouldn't care enough to offer advice.

Incidentally you would be well advised to stop using my as if it was a global declaration. What you call "in the normal way" I call "ill-advised". See RE (3): BrainPain-Help for my attempt to explain why. See how I used it above, moving the "my" as close to the initialization of the variable as possible? I do things that way on purpose.

A final note. Here is what I meant by making absolutely sure that you create a new variable each time:

for (my $i = 1; $i <= 8; ++$i) { my $really_private = $i; push( @ref_list, sub { print "\t$really_private\n" } ); } $_->() foreach @ref_list;
See? I am explicitly using a variable scoped to be private per instance of the loop. If this appears cumbersome, it makes more sense in a constructor. Take this simple example:
sub ret_simple_formatter { my $fmt = shift; return sub {sprintf($fmt, shift);}; }
Call that in a loop and it just works perfectly. :-)

BTW I have used almost exactly that function while developing code to set up a hash of field handlers. As the code matured, of course, most of the fields got better formatters than that. But it worked nicely for a first pass...