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

Sometimes a subroutine needs to have some way to refer to itself (usually for recursion). For named subs, it's simple - just use the name, exactly like you would do in C or in other languages:

sub recurse { my $level = shift; print "recurse [$level]\n"; recurse($level - 1) if $level > 0; }

However, there are ways to subvert this type of reference. Consider the following code:

#!/usr/bin/perl -w use strict; local $\ = "\n"; sub oldsub { my $level = shift; print "oldsub [$level]"; oldsub($level - 1) if $level > 0; } sub newsub { print "newsub [$_[0]]"; } my $oldsub_ref = \&oldsub; $oldsub_ref->(2); print '-' x 10; *oldsub = \&newsub; $oldsub_ref->(2);

with the output:

oldsub [2] oldsub [1] oldsub [0] ---------- Subroutine main::oldsub redefined at ./typeglob_clobber.pl line 22. oldsub [2] newsub [1]

This is, I must admit, an unlikely situation (and it's caught by warnings). Clobbering the typeglob of a named sub, while holding a reference to the original crosses the borderline of sanity IMHO (in for-production code at least). But you never know... Careless use of run-time compilation constructs like do or eval comes to mind. Anyway, advocating against recursion-by-name is not the point of my post.

For an anonymous sub, a safe way to hold a reference to itself is to embed it inside an outer closure:

my $coderef = do { my $selfref; $selfref = sub { # use $selfref here for recursion }; };

This way, the sub can use the cloistered $selfref confidently, because no outer code can clobber it (well, unless the sub leaks out references to it, of course).

Of course it's possible to use this method in order to "bulletproof" named subs too, if you're really paranoid. A named sub defined this way won't suffer from the problems present in the first code snippet:

{ my $selfref; sub named { # use $selfref here } $selfref = \&named; }

All this is OK and fine with me, but I still wonder - is there a generic, built-in way to get the reference to the currently running subroutine? Someting in the caller spirit? I was surprised to find out that caller offers pretty much everything in terms of introspection, except for code references. Maybe I'm overlooking something?

Replies are listed 'Best First'.
Re: sub getting reference to itself : generic way
by Limbic~Region (Chancellor) on Jun 18, 2004 at 16:33 UTC
    calin,
    I am completely out of my element here, but does Devel::Caller (advertised as meatier) or any of the other CPAN related modules fit the bill?

    Cheers - L~R

      Yep, it seems to do (though it's not built-in OR standard). Untested:

      use Devel::Caller 'caller_cv'; sub foo { my $selfref = caller_cv(0); # ... }
        Joost,
        *Chuckle* - I will share a snippet of the CB conversation I had along those lines:
        • Corion Seems like calin wants something like caller(-1) ... I wonder more about caller(-2) though - now that would be a feature of Perl to make other languages envious :-)
        • Limbic~Region was just reading that Corion
        • Corion Hmm - no, caller(0) does almost everything calin wants, except that it only returns a name not a reference ... But why should caller be restricted to non-negative numbers ? :-))))
        • Limbic~Region *shrug* - I am betting someone comes up with a B:: solution or something though the question looked to be asking for something generic
        • Limbic~Region does Devel::Caller fill in the missing code ref?
        • Corion Limbic~Region++ indeed!
        • Zaxo suspects diotalevi will come up with something clever and wicked
        Note: Quotes used with permission

        Cheers - L~R

Re: sub getting reference to itself : generic way
by Joost (Canon) on Jun 18, 2004 at 16:48 UTC
    my $oldsub_ref = \&oldsub; $oldsub_ref->(2); print '-' x 10; *oldsub = \&newsub; $oldsub_ref->(2);

    I guess it all depends on what you want here. You are explicitly redefining a subroutine, while you're keeping a code-ref to the old definition.

    Note that, if you call the new definition everything works as expected.

    If you really want the recursive call from the old defenition to always go to the old definition, you could do this (you already showed this at the end of your post):

    my $sref = \&oldsub; sub oldsub { my $level = shift; print "oldsub [$level]"; $sref->($level - 1) if $level > 0; }
    So, yes, there is a more or less generic way of getting a reference to the running subroutine: take a reference before the subroutine gets redefined and the symbol table slot gets overwritten. AFAIK there is no way to get at it afterwards.

    First of all, usually there are no references to the subroutine anymore, and it should be garbage collected, so the old defenition is gone anyway. (This might not happen, as I recall GC-ing subrefs is buggy in most perls)

    And assuming somebody keeps a reference around, maybe, by messing with the DB package, you could try and find it, but it would probably not be very efficient, and very ugly.

Re: sub getting reference to itself : generic way
by dave_the_m (Monsignor) on Jun 19, 2004 at 09:37 UTC
    my $coderef = do { my $selfref; $selfref = sub { # use $selfref here for recursion }; };
    Note that this will cause a memory leak; it's a high-tech variant of $a = \$a.

    Dave.