in reply to RE: RE (tilly) 1: for loops, closures
in thread for loops, closures
Do you see what happened there?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; }
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:
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:for (my $i = 1; $i <= 8; ++$i) { my $really_private = $i; push( @ref_list, sub { print "\t$really_private\n" } ); } $_->() foreach @ref_list;
Call that in a loop and it just works perfectly. :-)sub ret_simple_formatter { my $fmt = shift; return sub {sprintf($fmt, shift);}; }
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...
|
|---|