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