demerphq (re)discovered this little glitch, and describes it well. I'm going to add a bit, since it can be helpful to take a different view of the same problem. Here are some minimal cases, leaving off strict and warnings just because they're not very relevant...
{ my $foo = "Foo!\n"; sub makefoo { *foo = sub { print $foo }; $foo; } } makefoo(); foo();
Prints 'Foo!' just as you'd expect. Or as I'd expect, anyway.
{ my $foo = "Foo!\n"; sub makefoo { *foo = sub { print $foo }; } } makefoo(); foo();
Prints nothing at all. If you expected this, you're either deeper in Perl lore than I, or you have a sick mind. That's an inclusive or.
Thing is, the package sub &foo is being defined at compile time, and the anonymous sub within only at run time. That lone $foo statement in the first example, is a reference to the variable $foo, keeping it alive after $foo has gone out of scope, and available for the newly generated sub. Without the seemingly irrelevant statement, $foo is undefined. Apparently Perl doesn't look inside the subroutine to be generated for such references. Which makes some sense, I guess, because figuring out what code will be generated later is hard. I guess. Anyway...
{ my $foo = "Foo!\n"; *makefoo = sub { *foo = sub { print $foo }; } } makefoo(); foo();
Prints 'Foo!'. &makefoo is defined at runtime.
my $foo = "Foo!\n"; sub makefoo { *foo = sub { print $foo }; } makefoo(); foo();
Prints 'Foo!'. Fine and dandy... no closure-type stuff going on here. Which is evident because:
my $foo = "Foo!\n"; sub makefoo { *foo = sub { print $foo }; } $foo = "Moo!\n"; makefoo(); foo();
Prints 'Moo!'. $foo is still around when &makefoo gets called, so even though &makefoo doesn't carry a reference around with it, the var is still hanging around for &makefoo to use.
In my book, the compile-time run-time stuff definitely counts as weird. The $foo in the generated sub isn't doing what I mean, and the $foo statement in &makefoo is doing more than I expect. Oh well. No sense whining... I guess it's good for me. ;-)
In reply to Re: Funkyness with closures...
by Petruchio
in thread Funkyness with closures...
by demerphq
For: | Use: | ||
& | & | ||
< | < | ||
> | > | ||
[ | [ | ||
] | ] |