On 24 May 2000, Randal L. Schwartz wrote:
> >>>>> "tayers" == <[EMAIL PROTECTED]> writes:
>
> tayers> Given the above more complete descriptions I would say the usage in
> tayers> L<perlsub> is confusing.
>
> I agree with that, and with your general observation. From my hanging
> out on P5P, a subroutine is only a closure when it sees lexical
> variables and must therefore create a distinct clone of the
> environment on the way out.
>
> And both named subroutines and anonymous subroutines can be closures.
>
> Here's how to tell if a subroutine is a closure or not:
>
> for (1..5) {
> push @a, sub { "hi there" };
> }
> for (1..5) {
> {
> my $b;
> push @b, sub { $b."hi there" };
> }
> }
> print "anon normal: @a\n";
> print "anon closure: @b\n";
>
> which generates
>
> anon normal: CODE(0x80ce9d4) CODE(0x80ce9d4) CODE(0x80ce9d4) CODE(0x80ce9d4)
>CODE(0x80ce9d4)
> anon closure: CODE(0x80c83ac) CODE(0x80d2440) CODE(0x80d24a0) CODE(0x80d2500)
>CODE(0x80d2560)
>
> Note how each coderef from the non-closure is identical, but the
> closure form must generate distinct coderefs to point at the distinct
> instances of the closure.
>
> This is the underpinnings of that famous "won't stay shared" message.
> A "my" variable in a named subroutine context is generating distinct
> coderefs.
>
> So, in summary, "closure" vs "non-closure", and "named subroutine" vs
> "anonymous subroutine" are orthogonal concepts. Pick one from each
> column. :) And it's too bad that we have people mixing the terms up,
> because cargo-cult meme virus items spread fast in the Perl extended
> community.
Well, it's been about 6 months ago when Randal wrote this, but only now
I've finally got the time to reply to this. That's why the whole post is
quoted.
Apparently, the above explanation is not so complete and clear and while
"closure" vs "non-closure", and "named subroutine" vs "anonymous
subroutine" are indeed orthogonal concepts, only the "closure"+"anonymous
subroutine" appears to work, and "closure"+"named subroutine" is something
that should never happen, unless it's a desired effect and then the
programmer knows what's he doing.
Here is the part that Randal didn't post:
And now the same with named subroutines:
for (1..5) {
sub a { "hi there" };
push @a, \&a;
}
for (1..5) {
{
my $b;
sub b { $b."hi there" };
push @b, \&b;
}
}
print "normal:\n", join "\t\n",@a,"\n";
print "closure:\n",join "\t\n",@b,"\n";
which generates:
anon normal:
CODE(0x80568c0)
CODE(0x80568c0)
CODE(0x80568c0)
CODE(0x80568c0)
CODE(0x80568c0)
anon closure:
CODE(0x8056998)
CODE(0x8056998)
CODE(0x8056998)
CODE(0x8056998)
CODE(0x8056998)
We can see that both versions has generated the same code reference. For
the subroutine I<a> it's easy, since it doesn't include any lexical
variables defined outside it in the same lexical scope.
As for the subroutine I<b>, it's indeed a closure sub, but Perl won't
recompile it since it's a named subroutine (see the perlsub manpage). It's
something that we don't want to happen in our code.
This is the underpinnings of that famous I<"won't stay shared"> message.
A I<my> variable in a named subroutine context is generating identical
code references and therefore it ignores any future changes to the lexical
variables outside of it.
BTW, for those who aren't yet familiar with the famous I<"won't stay
shared"> message and the prove that "closure"+"anonymous subroutine" work,
please read:
http://perl.apache.org/guide/perl.html#my_Scoped_Variable_in_Nested_S
Thanks!
_____________________________________________________________________
Stas Bekman JAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide http://perl.apache.org/guide
mailto:[EMAIL PROTECTED] http://apachetoday.com http://jazzvalley.com
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]