Sub::Uplevel - apparently run a function in a higher stack frame |
Sub::Uplevel - apparently run a function in a higher stack frame
This documentation describes version 0.22
use Sub::Uplevel;
sub foo { print join " - ", caller; }
sub bar { uplevel 1, \&foo; }
#line 11 bar(); # main - foo.plx - 11
Like Tcl's uplevel()
function, but not quite so dangerous. The idea
is just to fool caller()
. All the really naughty bits of Tcl's
uplevel()
are avoided.
THIS IS NOT THE SORT OF THING YOU WANT TO DO EVERYDAY
uplevel $num_frames, \&func, @args;
Makes the given function think it's being executed $num_frames higher
than the current stack level. So when they use caller($frames)
it
will actually give caller($frames + $num_frames) for them.
uplevel(1, \&some_func, @_)
is effectively goto &some_func
but
you don't immediately exit the current subroutine. So while you can't
do this:
sub wrapper { print "Before\n"; goto &some_func; print "After\n"; }
you can do this:
sub wrapper { print "Before\n"; my @out = uplevel 1, &some_func; print "After\n"; return @out; }
uplevel
will issue a warning if $num_frames
is more than the current call
stack depth.
=back
The main reason I wrote this module is so I could write wrappers around functions and they wouldn't be aware they've been wrapped.
use Sub::Uplevel;
my $original_foo = \&foo;
*foo = sub { my @output = uplevel 1, $original_foo; print "foo() returned: @output"; return @output; };
If this code frightens you you should not use this module.
Well, the bad news is uplevel()
is about 5 times slower than a normal
function call. XS implementation anyone? It also slows down every invocation
of caller()
, regardless of whether uplevel()
is in effect.
Sub::Uplevel overrides CORE::GLOBAL::caller temporarily for the scope of each uplevel call. It does its best to work with any previously existing CORE::GLOBAL::caller (both when Sub::Uplevel is first loaded and within each uplevel call) such as from Contextual::Return or Hook::LexWrap.
However, if you are routinely using multiple modules that override CORE::GLOBAL::caller, you are probably asking for trouble.
You should load Sub::Uplevel as early as possible within your program. As with all CORE::GLOBAL overloading, the overload will not affect modules that have already been compiled prior to the overload. One module that often is unavoidably loaded prior to Sub::Uplevel is Exporter. To forceably recompile Exporter (and Exporter::Heavy) after loading Sub::Uplevel, use it with the ":aggressive" tag:
use Sub::Uplevel qw/:aggressive/;
The private function Sub::Uplevel::_force_reload()
may be passed a list of
additional modules to reload if ":aggressive" is not aggressive enough.
Reloading modules may break things, so only use this as a last resort.
As of version 0.20, Sub::Uplevel requires Perl 5.6 or greater.
Those who do not learn from HISTORY are doomed to repeat it.
The lesson here is simple: Don't sit next to a Tcl programmer at the dinner table.
Thanks to Brent Welch, Damian Conway and Robin Houston.
David A Golden <dagolden@cpan.org> (current maintainer)
Michael G Schwern <schwern@pobox.com> (original author)
Original code Copyright (c) 2001 to 2007 by Michael G Schwern. Additional code Copyright (c) 2006 to 2008 by David A Golden.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
See http://www.perl.com/perl/misc/Artistic.html
PadWalker (for the similar idea with lexicals), Hook::LexWrap,
Tcl's uplevel()
at http://www.scriptics.com/man/tcl8.4/TclCmd/uplevel.htm
Sub::Uplevel - apparently run a function in a higher stack frame |