Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Re: A Real Closure

by John M. Dlugosz (Monsignor)
on Jul 12, 2001 at 18:32 UTC ( #96045=note: print w/ replies, xml ) Need Help??


in reply to A Real Closure
in thread Unusual Closure Behaviour

The docs are pretty clear that using sub to create a ref to an anonomous sub will do closures and that a normal named sub will not.

So I tried it. It gives me a warning that "$x will not stay shared", but the result seems to work! That is, a created named function seems to reference the same variable as a standard closure created in the same scope, and running the creator again (which makes a different local $x) keeps distinct identities.

So what's going on here? Are the docs outdated? Is this working by accident or happenstance? Does the presence of a regular closure somehow make it work?

—John

use v5.6.1; # Active State build 626 use strict; use warnings; sub outer { my $x= shift; my $name= shift; my $closure= sub { return $x++; }; eval "sub $name { return \$x++; }"; return $closure; } my $r1= outer (1, 'f1'); my $r2= \&f1; print $r1->(), $r2->(), "\n"; my $r3= outer ('A', 'f2'); my $r4= \&f2; print $r3->(), $r4->(),$r3->(), $r4->(), "\n"; print $r1->(), $r2->(),$r1->(), $r2->(), "\n";


Comment on Re: A Real Closure
Download Code
Re: Re: A Real Closure
by japhy (Canon) on Jul 12, 2001 at 18:41 UTC
    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
      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.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://96045]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (9)
As of 2014-09-23 03:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (210 votes), past polls