Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

weaken CODEREF

by powerman (Friar)
on Nov 11, 2013 at 01:21 UTC ( #1061941=perlquestion: print w/replies, xml ) Need Help??

powerman has asked for the wisdom of the Perl Monks concerning the following question:

Looks like weaken doesn't support CODE:
$ perl -MScalar::Util=weaken -E '$a={}; weaken($b=$a);$a=0;say $b' $ perl -MScalar::Util=weaken -E '$a=sub{};weaken($b=$a);$a=0;say $b' CODE(0x5964f33f920)
Is this a bug or feature? Tested on perl-5.12.4, Scalar::Util-1.35.

Update: More details on

Replies are listed 'Best First'.
Re: weaken CODEREF
by dave_the_m (Monsignor) on Nov 11, 2013 at 09:14 UTC
    Its a feature (of sorts) and it's unrelated to weaken(). When an anonymous sub is compiled, a "prototype" sub (CV) is created. At run time, whenever 'sub {...}' is executed, a copy of that prototype CV is made, as you would expect.

    However, as an optimisation (with unfortunately visible side effects), if that CV isn't closing over any outer lexicals, the CV isn't copied, it's shared: so its ref count is bumped and a new reference to it is returned. Which is what you're seeing here.

    The other common visible side-effect is this:

    for (1,2) { push @a, sub {}; my $lex; push @b, sub { $lex }; } bless $a[0]; bless $b[0]; print "$a[1] $b[1]\n";

    which outputs

    main=CODE(0x1f41648) CODE(0x1f40c88)

    Whoops, $a[1] is blessed too.

    No-ones thought of a way round this yet, but removing the optimisation would make simple anon subs a lot slower.


      Correctamundo! Usually this optimization doesn't cause any issues, but if you're finding that it does, the solution is to force Perl to close over a variable. A short string or small integer is ideal, as they'll waste very little memory.

      use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
Re: weaken CODEREF
by Athanasius (Bishop) on Nov 11, 2013 at 02:52 UTC

    I can confirm this behaviour on perl 5.18.1 with Scalar::Util 1.35. Looks like a bug to me.

    Note that the correct behaviour can be obtained using the experimental “lexical subroutines” feature, introduced in perl 5.18.0 (see perlsub):

    #! perl use strict; use warnings; use feature 'lexical_subs'; use Scalar::Util 'weaken'; my $ref; { my sub frobnicate { print 42; } my $local_ref = \&frobnicate; # $ref = $local_ref; weaken($ref = $local_ref); } $ref->();


    12:49 >perl The lexical_subs feature is experimental at line 10. Can't use an undefined value as a subroutine reference at +line 20. 12:49 >

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: weaken CODEREF
by Haarg (Curate) on Nov 11, 2013 at 09:59 UTC

    Also, weaken is working properly on the coderef. You can see this by checking the ref counts using Devel::Peek. The ref count just never reaches 0 because perl itself is holding the last reference.

    Weakening a non-closure sub is also not particularly useful. Weakening is meant to be used to prevent memory leaks, but the existence of a non-closure sub can't cause memory leaks. perl has to have a reference to the compiled sub anyway, and without a closure you can't create reference loops.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1061941]
Approved by LanX
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (4)
As of 2020-12-01 12:56 GMT
Find Nodes?
    Voting Booth?
    How often do you use taint mode?

    Results (6 votes). Check out past polls.