Re: Interesting behaviour with lexical variable



Michele Dondi schrieb:
On Mon, 30 Oct 2006 17:37:43 +0100, "Ferry Bolhar"
<bol@xxxxxxxxxxxxxxxxx> wrote:

while playing with code like this:

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

sub add {
$num + $num;
}
}

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().

This has been discussed before. Actually I have been claiming that
contrary to the common assumption, closures are an orthogonal concept
to that of anonymous subs. I was wrong: this turns out to be true in
general, but it has been shown to me that in Perl (5, that is, in 6 I
don't know (yet)) closures are only implemented as anonymous subs,
since as you discovered yourself, named ones only close around the
lexical scope surrounding them as of the first time they're found,
thus failing to take a 'snapshot' of those lexicals at any given time,
which is a fundamental closure charachteristic.

I believe you're doing the word "closure" a bit of injustice
here, just because most examples and descriptions out there
mix up closures and function templates. The latter ones being
implement as anonymous subs in Perl, that much is true.

However, I agree very much with Randal L. Schwartz in that
any kind of subroutine that "freezes" it referenced lexicals
from the surrounding scope is a closure. To me, the definition
that a closure is created every time the sub referencing outside
lexicals is created, still holds true.

Perl is just a bit trickier to understand in this regard,
because named subs have a longer lifetime than lexicals, which
isn't true for most functional languages, where the term stems
from. The sub is created only once, so it captures only once.
What would you call the sub "increment" in the following
example, if not a closure?

{
my $startcount = 5;
sub increment
{
++startcount;
}
}

Whether the surrounding block is just some text between curly
brackets, whether it has a "do" keyword in front, or whether it
makes up a loop or sub body, is in the first step of no importance
to Perl. It just gets important for the programmer to be aware of
due to the side effects that come up becasue named subs exist over
the whole package lifetime.

If you take a look at the perlref.pod in bleadperl and at
the devel version of perlfaq7 at
https://svn.perl.org/modules/perlfaq/trunk
you'll see that this reasonings are reflected in the docs now.

-Chris
.



Relevant Pages

  • Re: What does `my do?!
    ... You could put the anonymous sub def in a begin block, ... I think the essence of a closure is what it ... named sub is still a closure, it is just one that has an implicit BEGIN ... compile time) and a new pad with refs to the currently-outer lexicals. ...
    (comp.lang.perl.misc)
  • Re: What does `my do?!
    ... ref to the outer lexicals as they existed then. ... sub foo ... Sure, anonymous subs are more useful in such situations, but I think that what triggers recompilation is an accident of the language, and not the essence of a closure. ... So I think a named sub is still a closure, it is just one that has an implicit BEGIN block around it, and so only compiles once unless you take steps to change that. ...
    (comp.lang.perl.misc)
  • Re: Interesting behaviour with lexical variable
    ... Note that $num in the loop is *not* the same variable each time, ... The named sub addfirmly believes ... I wouldn't think that a closure knows about the changes. ...
    (comp.lang.perl.misc)
  • Re: arguments in closure
    ... > I understand the mechanism of the closure, ... the anonymous sub returned by make_binary is ... There are no vars, but only a constant. ...
    (perl.beginners)
  • Re: Interesting behaviour with lexical variable
    ... Note that $num in the loop is *not* the same variable each time, ... The named sub addfirmly believes ... I wouldn't think that a closure knows about the changes. ...
    (comp.lang.perl.misc)