in reply to Re: A Real Closure
in thread Unusual Closure Behaviour

Err, the warning is due to defining a function (that ends up acting as a closure, due to its use of lexicals defined in an upper scope) inside a function. But if you write:
{ my $x; sub count { ++$x } }
Then $x is private to &count, and because &count refers to a lexical that "should" have "gone away", it is a closure. At least, that is what I have understood from Randal.

japhy -- Perl and Regex Hacker

Replies are listed 'Best First'.
Re: Re: Re: A Real Closure
by John M. Dlugosz (Monsignor) on Jul 12, 2001 at 18:50 UTC
    That's not the same thing. $x is not in the package symbol table, but it still has a persistant identity. The compiler looks up the SV and points to it, and it stays that way. It's just like any other variable that's bound at compile time. Not being in the symbol table but in a lex table instead doesn't change the generated code.

    The "closure" issue refers to a specific instance of a variable that keeps changing its identity. In a function, $x is a different SV each time it is called. The creation point of a closure uses the current one. The creation of the closure takes place after the my has its run-time effects. Your example creates count at compile-time

    the warning is due to defining a function (that ends up acting as a closure, due to its use of lexicals defined in an upper scope) inside a function
    You'll get that warning no matter how you contrive to create a named sub refering to a lexical variable that gets re-bound with each pass through the code.
      But still japhy is right.

      A closure is a subroutine that contains a reference to a lexical bound to it at its creation. In the case of named functions created within a scope where Perl thinks that you are likely to have multiple variables masquerading as that lexical, Perl gives you a warning because only one variable will get bound to the function, and on your next time through the code what goes in that lexical will not be reflected in the named sub.

      That is why you got a warning.

      However it worked anyways because you expected the global to be tied to the variable created with that lexical scope that it is, in fact, tied to.

      And it would have worked had you pushed it farther because after each pass you would wipe out any existing function of that name and create a new one bound to the current lexical.

      So you are being warned about something that might not work as you expect which actually will work as you expect. But it works exactly as it is supposed to. Is that a bug? Not in my books. Perl does what it is supposed to, and warnings are flagged specifically because they are constructs which indicate that things may be wrong in your program, but which might be just fine in reality.