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/"

Reply via email to