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 | |
by calin (Deacon) on Jun 18, 2004 at 16:53 UTC | |
by Joost (Canon) on Jun 18, 2004 at 16:53 UTC | |
by Limbic~Region (Chancellor) on Jun 18, 2004 at 17:01 UTC | |
|
Re: sub getting reference to itself : generic way
by Joost (Canon) on Jun 18, 2004 at 16:48 UTC | |
|
Re: sub getting reference to itself : generic way
by dave_the_m (Monsignor) on Jun 19, 2004 at 09:37 UTC |