Why turn warnings off? Turning them on (and autoflushing STDOUT and STDERR, so the output is in order) prints:
Useless use of private variable in void context at myscript.pl line 27 +. factory: 'lulz' eval: 'lulz' factory: 'frunz' Variable "$var" is not available at (eval 2) line 1. Use of uninitialized value $var in concatenation (.) or string at (eva +l 2) line 1. eval: '' factory: 'lulz' eval: 'lulz'
In the first factory, you're using $var in an eval{} block... which is quite different from a string eval(). This isn't an interesting case, and works as you expected anyway.
The difference between your second and third examples is the supposedly useless (as perl tells you) statement $var. The compressed answer is that when you generate the closure in these latter cases, perl has no idea that you're making use of $var in your block, and so it sees no reason to include it in the closure.
After all, all perl sees is a string and some function call (to eval()). But when you explicitly make use of $var in your (third) factory, perl includes it in the closure - not because it knows you're going to need it, but because you included it. When the string eval is then evaluated, it finds $var in the third factory, but can't resolve it in the second factory.
To make sure it is clear what I am referencing from a closure, I always like to explicitly write out which variables I need for it... I'd write something like:
return sub{ my ($code) = ($var); my $estr = "print \"eval: '\$code'\n\""; eval $estr; }
In reply to Re: i don't understand this scope behavior w/ closures and eval
by crashtest
in thread i don't understand this scope behavior w/ closures and eval
by xandercrews
For: | Use: | ||
& | & | ||
< | < | ||
> | > | ||
[ | [ | ||
] | ] |