Re: Interesting behaviour with lexical variable
- From: anno4000@xxxxxxxxxxxxxxxxxxxxxx
- Date: 30 Oct 2006 19:57:59 GMT
jl_post@xxxxxxxxxxx <jl_post@xxxxxxxxxxx> wrote in comp.lang.perl.misc:
Ferry Bolhar wrote:
Hi to all,
while playing with code like this:
use warnings;
while (my $input = <STDIN>){
my $num = abs $input;
print add();
sub add {
$num + $num;
}
}
Unless you really know what you're doing, you should never define a
function inside a loop or another function. In fact, many Perl
programmers (me included) recommend that all your functions be defined
at the top of your script, before you start your main code. Do that,
and your problem will go away.
I found out that once the loop get executed for the second
time, the variable $sum gets "splitted", taking the new value
from $input in the loop, but leaving the old, previous value
in add().
I believe that's because the add() function is never defined until
the first time through the loop.
That isn't quite correct. The sub add() is defined at compile time, not
the first time through the loop. Proof: Add
die 'boo' unless defined &add;
before the loop. It won't die.
The confusing behavior is caused by sub dispatch, which is the
mechanism by which closures retain the lexical environment that
is present when the coderef is assigned. If sub add() is replaced
by an actual closure, the confusing behavior goes away:
while (my $input = <STDIN>){
my $num = abs $input;
my $add = sub {
$num + $num;
};
# sub add { $num + $num }
print $add->(), "\n";
}
prints a new value (the expected one) each time through, because
the sub is dispatched with the current value each time.
A named sub, as in the commented-out line is dispatched only once
and freezes that value of $num. I don't claim to know how this
happens exactly, but that's what it amounts to.
Note that $num in the loop is *not* the same variable each time,
as printing the ref shows. The named sub add() firmly believes
in the very first variable named $num (and its value) while the
loop advances and uses a new one every time. A closure knows
about the changes.
Anno
.
- Follow-Ups:
- Re: Interesting behaviour with lexical variable
- From: jl_post@xxxxxxxxxxx
- Re: Interesting behaviour with lexical variable
- References:
- Interesting behaviour with lexical variable
- From: Ferry Bolhar
- Re: Interesting behaviour with lexical variable
- From: jl_post@xxxxxxxxxxx
- Interesting behaviour with lexical variable
- Prev by Date: Re: Perl equivalent to unix script
- Next by Date: Re: Handling a 450,000x450,000 array with Perl
- Previous by thread: Re: Interesting behaviour with lexical variable
- Next by thread: Re: Interesting behaviour with lexical variable
- Index(es):
Relevant Pages
|
|