On 9/20/07, flw <[EMAIL PROTECTED]> wrote:
> C:\>cat ttt.pl
> use strict;
> use warnings;
>
> {
> my $x = 'A';
> sub f { sub { $x++ } }
> sub g { sub { $x++ } if $x }
> }
>
> my $F=f();
> my $G=g();
>
> print $F->(),$G->(),"," for 1..4;
> print "\n";
>
> C:\>ttt.pl
> 0A,1B,2C,3D,
>
> C:\>
Known bug in closure implementation. Since sub f doesnt mention $x the
sub that it returns doesnt enclose the same $x as the sub returned by
g().
Changing the code to read
{
my $x = 'A';
sub f { sub { print \$x; $x++ } }
sub g { sub { print \$x; $x++ } if $x }
}
Produces:
SCALAR(0x225f18)
SCALAR(0x226d4c)
0A,
SCALAR(0x225f18)
SCALAR(0x226d4c)
1B,
SCALAR(0x225f18)
SCALAR(0x226d4c)
2C,
SCALAR(0x225f18)
SCALAR(0x226d4c)
3D,
Which shows that the two are operating on different scalars. I had
guessed that the f() sub would be operating on $::x but it turns out
that it isnt. Somehow *two* $x'es are being created. Which i find
surprising even though i know about this bug.
The solution is to add a dummy line to f() to make sure that it mentions $x.
{
my $x = 'A';
sub f { my $y=$x; sub { print \$x; $x++ } }
sub g { sub { print \$x; $x++ } if $x }
}
Will cause both subs to bind to the same scalar.
Cheers,
Yves
--
perl -Mre=debug -e "/just|another|perl|hacker/"