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

You can get lucky (as you did with looping over a list) and have it work by accident, but the safest approach is to make absolutely sure that you have created a new variable each time with "my".

Yes, but using my in the normal place does nothing at all solve the problem. As for "getting lucky," just because because there is a structure I experimented with and failed, doesn't mean the way I did it that did work worked by luck.

Paris Sinclair    |    4a75737420416e6f74686572
pariss@efn.org    |    205065726c204861636b6572
http://sinclairinternetwork.com

Replies are listed 'Best First'.
RE (tilly) 3: for loops, closures
by tilly (Archbishop) on Aug 20, 2000 at 21:43 UTC
    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...