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


in reply to No DESTROY object.

sub {} does not refer to any lexical variables, so it is optimized to always return a reference to the same sub, instead of creating subs every time. Thus, that sub is never destroyed. For example, see that this prints the same address twice.

perl -we 'sub f { sub { } }; $x = f(); $y = f(); warn "$x $y";'

In comparision, if you get a reference with an array or hash constructor [] or {}, or with a lexical variable like do {\my $t} or do {\my @a}, you always get a fresh one because arrays and hashes are mutable.

Update: sorry, originally I posted the wrong example code, the one that shows when the sub does refer to a lexical variable, so the two calls to f returned subs that referred to two different variables, thus, the addresses were different. It's now corrected above, below is that old code.

perl -we 'sub f { my $t; sub { $t } }; $x = f(); $y = f(); warn "$x $y +";'

Replies are listed 'Best First'.
Re^2: No DESTROY object.
by JavaFan (Canon) on Jan 22, 2010 at 14:36 UTC
    That prints two different addresses. But since it's a sub that does refer to a lexical variable, it neither proves, nor disproves your claim about optimization.

    But note this:

    $ perl5.10.1 -we 'sub f { our $t; sub { $t } }; $x = f(); $y = f(); wa +rn "$x $y";' CODE(0x95ca930) CODE(0x95ca930) at -e line 1.
    Same address. But not so in 5.8.9
    $ perl5.8.9 -we 'sub f { our $t; sub { $t } }; $x = f(); $y = f(); war +n "$x $y";' CODE(0x867218c) CODE(0x8672258) at -e line 1.
Re^2: No DESTROY object.
by WizardOfUz (Friar) on Jan 22, 2010 at 14:29 UTC
    For example, see that this prints the same address twice.

    No, it does not, at least not in perl v5.10.0:

    perl -we 'sub f { my $t; sub { $t } }; $x = f(); $y = f(); warn "$x $y +";' CODE(0x82998c4) CODE(0x8299964) at -e line 1.

    Has perl become smarter?

Re^2: No DESTROY object.
by gam3 (Curate) on Jan 22, 2010 at 17:15 UTC
    There are 2 problems with your argument that jump out at me.
    1. first - DESTROY should still get called even if only once.
    2. second sub { $bob } does not get DESTROYed either and it certainly not immutable.
    package Foo; sub print { print "@_\n"; } sub DESTROY { print "@_ DESTROY\n"; } our $bob = "x\n"; my $x = bless(sub {$bob}, 'Foo'); $x->print('$bob'); print $x->(); $bob = "y\n"; print $x->(); $bob = undef; __END__ Foo=CODE(0xe8a278) $bob x y
    -- gam3
    A picture is worth a thousand words, but takes 200K.

      For your second question, if you replace our $bob to my $bob, then the DESTROY does get called. This way, perl knows that $bob is a global so it optimizes the sub constructor to a constant again.