Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Closures (was Re: for loops)

by merlyn (Sage)
on Aug 20, 2000 at 21:48 UTC ( #28733=note: print w/replies, xml ) Need Help??


in reply to for loops, closures

One of the things when I get an unexpected closure binding is to print both the reference to the variables I'm expecting to be bound, and the resulting coderef. By watching the addresses change (or not) I can tell whether the variables have independant binding (or not). For example:
for ($i = 1; $i <= 8; $i++) { print "\\\$i is ", \$i, "\n"; my $c = sub { print "\$i is $i\n" }; print "\$c is $c\n"; push @codes, $c; }
For this one, I got:
\$i is SCALAR(0x80ce98c) $c is CODE(0x80cea04) \$i is SCALAR(0x80ce98c) $c is CODE(0x80cea04) \$i is SCALAR(0x80ce98c) $c is CODE(0x80cea04) \$i is SCALAR(0x80ce98c) $c is CODE(0x80cea04) \$i is SCALAR(0x80ce98c) $c is CODE(0x80cea04) \$i is SCALAR(0x80ce98c) $c is CODE(0x80cea04) \$i is SCALAR(0x80ce98c) $c is CODE(0x80cea04) \$i is SCALAR(0x80ce98c) $c is CODE(0x80cea04)
showing that we are neither looking at distinct $i nor a closure (the addresses are all identical). Now, let's add a my declaration:
for (my $i = 1; $i <= 8; $i++) { print "\\\$i is ", \$i, "\n"; my $c = sub { print "\$i is $i\n" }; print "\$c is $c\n"; push @codes, $c; }
and notice that we now get a closure (the coderef addresses change):
\$i is SCALAR(0x80ce974) $c is CODE(0x80c83ac) \$i is SCALAR(0x80ce974) $c is CODE(0x80d22f8) \$i is SCALAR(0x80ce974) $c is CODE(0x80d2364) \$i is SCALAR(0x80ce974) $c is CODE(0x80d23d0) \$i is SCALAR(0x80ce974) $c is CODE(0x80d243c) \$i is SCALAR(0x80ce974) $c is CODE(0x80d24a8) \$i is SCALAR(0x80ce974) $c is CODE(0x80d2514) \$i is SCALAR(0x80ce974) $c is CODE(0x80d2580)
So, even though these are all closures, they are all linked to the same now changed $i. This will protect them for when the $i goes out of scope, but they still all share the same one. What we need is to have a "different" $i each time:
foreach my $i (1..8) { print "\\\$i is ", \$i, "\n"; my $c = sub { print "\$i is $i\n" }; print "\$c is $c\n"; push @codes, $c; }
Ahh, there we go, now we got it:
\$i is SCALAR(0x80c83ac) $c is CODE(0x80ce95c) \$i is SCALAR(0x80d21b8) $c is CODE(0x80d21c4) \$i is SCALAR(0x80d2230) $c is CODE(0x80d223c) \$i is SCALAR(0x80d22a8) $c is CODE(0x80d22b4) \$i is SCALAR(0x80d2320) $c is CODE(0x80d232c) \$i is SCALAR(0x80d2398) $c is CODE(0x80d23a4) \$i is SCALAR(0x80d2410) $c is CODE(0x80d241c) \$i is SCALAR(0x80d2488) $c is CODE(0x80d2494)
See the distinct $i variables, as well as the closures created for them!

Hopefully, this kind of reference-to examination will give you more clues faster when you can't see why things are shared or not. Very helpful for those $x won't stay shared diagnostics.

-- Randal L. Schwartz, Perl hacker

Replies are listed 'Best First'.
RE: Closures (was Re: for loops)
by Aighearach (Initiate) on Aug 21, 2000 at 05:26 UTC
    Thanks, Randal. Earlier today I was using that technique to flush keys and values out of a poorly documented object (Gtk), but of course it didn't occur to me to use it here. "Very helpful" indeed, hopefully it will help make my debugging toolkit more genericized.
    Paris Sinclair    |    4a75737420416e6f74686572
    pariss@efn.org    |    205065726c204861636b6572
    http://sinclairinternetwork.com
    

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (4)
As of 2023-09-30 00:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?