Re: Interesting behaviour with lexical variable



anno4000@xxxxxxxxxxxxxxxxxxxxxx wrote:

while (my $input = <STDIN>){
my $num = abs $input;
my $add = sub {
$num + $num;
};
# sub add { $num + $num }
print $add->(), "\n";

}

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.

I wouldn't think that a closure knows about the changes. That
closure only knows about the changes because a new closure gets created
each time through the loop (each time using a new value of $num).

But define the closure only once and it will always use the value of
$num that it had the first time through the loop:

my $add;
while (my $input = <STDIN>){
my $num = abs $input;
$add = sub {
$num + $num;
} unless defined $add;
print $add->(), "\n";
}

With this code, the $add only get assigned a closure once, and keeps
the first value of $num each time.

Because of this behavior, I was under the impression that the
original poster's code:

while (my $input = <STDIN>){
my $num = abs $input;
print add();

sub add {
$num + $num;
}
}

behaved the same way for similar reasons. (And if you replace "my"
with "our" all pieces of code will work the way the original poster
intended.)

So although &add is indeed defined at the beginning of the script,
for some reason the add() function it refuses to "re-define" its own
behavior after the first time through the loop. (As to why this
happens, I'm really not sure...)

-- Jean-Luc

.



Relevant Pages