Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

RE (tilly) 1: for loops, closures

by tilly (Archbishop)
on Aug 20, 2000 at 18:50 UTC ( [id://28728]=note: print w/replies, xml ) Need Help??


in reply to for loops, closures

Ovid already got it, just some details.

Yes, I have searched for "for" in the documentation. I found it easier to search for "foreach" in "perlsyn" in the end. :-)

Your problem really is that you need to think carefully about what variables are created where and when. 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".

Incidentally there is a pretty good discussion of closures in the perltoot page. (And scattered through the other documentation. Try "perldoc -l perl", go to that directory, and start grepping for "closure". :-)

Replies are listed 'Best First'.
RE: RE (tilly) 1: for loops, closures
by Aighearach (Initiate) on Aug 20, 2000 at 19:48 UTC
    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
    
      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...

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://28728]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (3)
As of 2024-04-19 17:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found