http://www.perlmonks.org?node_id=255680


in reply to •Re: Re: Toggling between two values
in thread Toggling between two values

"closure" and "named" are orthogonal properties

I'm afraid that's not quite true, at least in Perl. Perl subs that are named are not closures, by fiat. This choice was made to prevent imposing closure overhead on subroutines that don't need closure behavior (i.e. the capturing of values at time of sub reference).

The rule, as best I recall, is: In Perl, a closure is an anonymous subroutine that accesses at least one lexical variable not declared at global scope. BTW, IIRC, BEGIN blocks are deemed to be global scope for the purpose of deciding whether a sub is a closure.

I do feel a bit weird correcting chip on this point.

Well, you should, since you're wrong. {grin}

    -- Chip Salzenberg, Free-Floating Agent of Chaos

Replies are listed 'Best First'.
•Re: Re: •Re: Re: Toggling between two values
by merlyn (Sage) on May 05, 2003 at 17:46 UTC
    But I thought the "not stay shared" error is because the closure stuff is triggering on a named subroutine (usually inside another one). Is that not being closed on the first invocation, and subsequent invocations creating different lex vars?

    And, on a completely different note, is this not a named closure?

    my $coderef = do { my $counter = 0; sub { ++$counter }; }; *named_closure = $coderef;
    That looks like I can call named_closure() to me, and it's a named closure.

    Perhaps that's not what

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      No, that's not the reason for "not stay shared". The reason is that the cloning procedure has to happen at a specific runtime moment when the lexical var(s) to be cloned are alive; however, an inner named sub inside an outer named sub has no specific runtime moment in which it can grab the var and clone it. Consider the situation if the outer sub is never called at all, but the inner sub is called by the main code: When could cloning occur? There's no opportunity. On the other hand, an anonymous sub is an expression which must be evaluated, and that moment of evaluation is the moment of cloning (if cloning is required).

      Your example should be a closure. However, if you find that it isn't, it's possible that the current algorithm for deciding whether a variable is at file scope (and therefore not in need of cloning) may be incorrectly ignoring the do BLOCK and other non-sub scoping structures. So if your code doesn't make a closure when exectued at file scope, you may want to file a bug.

      PS: The reason vars at file scope don't trigger closure behavior is that such vars are usually global in effect and live as long as the program does; cloning references to them is therefore of no use; it may even have caused a bug with sharing state once, though I'm not really sure, and I don't relish reviewing my old p5p mail for closure bugs....

          -- Chip Salzenberg, Free-Floating Agent of Chaos

Re: Re: •Re: Re: Toggling between two values
by jdporter (Paladin) on May 05, 2003 at 20:03 UTC
    I'm afraid that's not quite true, at least in Perl.
    Then Perl has it wrong.
    Perl subs that are named are not closures, by fiat.
    By fiat? Of whom? ;-)

    Merlyn has it right: being a closure and being named are orthogonal properties. OTOH, I'm not saying you are wrong, because you have experience in a strange, quantum-like world (aka perl internals) where the normal definitions don't necessarily apply.

    jdporter
    The 6th Rule of Perl Club is -- There is no Rule #6.

      Well, hm. Given this behavior:
      eval q{ my $foo = 1; sub bar { ++$foo } }; print &bar, &bar, &bar;

      Would you say that &bar is a closure? Because if it is, then I've been conflating closures in general with a specific subset of them, and I have some apologies to make....

          -- Chip Salzenberg, Free-Floating Agent of Chaos

        Would you say that &bar is a closure?
        Yes, it is, according to the standard definition.

        OTOH, there needs to be a term for "subroutine which is created at run time via the sub operator and thus may have bindings to lexicals which outlive the names of those lexicals"...

        jdporter
        The 6th Rule of Perl Club is -- There is no Rule #6.