use Return::MultiLevel qw(with_return);
sub inner {
my ($f) = @_;
$f->(42); # implicitly return from 'with_return' below
print "You don't see this\n";
}
sub outer {
my ($f) = @_;
inner($f);
print "You don't see this either\n";
}
my $result = with_return {
my ($return) = @_;
outer($return);
die "Not reached";
};
print $result, "\n"; # 42
DESCRIPTION
This module provides a way to return immediately from a deeply nested call
stack. This is similar to exceptions, but exceptions don’t stop automatically
at a target frame (and they can be caught by intermediate stack frames using
eval). In other words, this is more like
setjmp(3)/longjmp(3) than die.
Another way to think about it is that the “multi-level return” coderef
represents a single-use/upward-only continuation.
Functions
The following functions are available (and can be imported on demand).
with_return BLOCK
Executes BLOCK, passing it a code reference (called $return in this
description) as a single argument. Returns whatever BLOCK returns.
If $return is called, it causes an immediate return from with_return. Any
arguments passed to $return become with_return‘s return value (if
with_return is in scalar context, it will return the last argument passed to
$return).
It is an error to invoke $return after its surrounding BLOCK has finished
executing. In particular, it is an error to call $return twice.
DEBUGGING
This module uses unwind from
Scope::Upper to do its work. If
Scope::Upper is not available, it substitutes its own pure
Perl implementation. You can force the pure Perl version to be used regardless
by setting the environment variable RETURN_MULTILEVEL_PP to 1.
If you get the error message Attempt to re-enter dead call frame, that means
something has called a $return from outside of its with_return { ... }
block. You can get a stack trace of where that with_return was by setting
the environment variable RETURN_MULTILEVEL_DEBUG to 1.
CAVEATS
You can’t use this module to return across implicit function calls, such as
signal handlers (like $SIG{ALRM}) or destructors (sub DESTROY { ... }).
These are invoked automatically by perl and not part of the normal call chain.
Return::MultiLevel

Return across multiple call levels
SYNOPSIS
DESCRIPTION
This module provides a way to return immediately from a deeply nested call stack. This is similar to exceptions, but exceptions don’t stop automatically at a target frame (and they can be caught by intermediate stack frames using
eval). In other words, this is more like setjmp(3)/longjmp(3) thandie.Another way to think about it is that the “multi-level return” coderef represents a single-use/upward-only continuation.
Functions
The following functions are available (and can be imported on demand).
with_return BLOCK
Executes BLOCK, passing it a code reference (called
$returnin this description) as a single argument. Returns whatever BLOCK returns.If
$returnis called, it causes an immediate return fromwith_return. Any arguments passed to$returnbecomewith_return‘s return value (ifwith_returnis in scalar context, it will return the last argument passed to$return).It is an error to invoke
$returnafter its surrounding BLOCK has finished executing. In particular, it is an error to call$returntwice.DEBUGGING
This module uses
unwindfromScope::Upperto do its work. IfScope::Upperis not available, it substitutes its own pure Perl implementation. You can force the pure Perl version to be used regardless by setting the environment variableRETURN_MULTILEVEL_PPto 1.If you get the error message
Attempt to re-enter dead call frame, that means something has called a$returnfrom outside of itswith_return { ... }block. You can get a stack trace of where thatwith_returnwas by setting the environment variableRETURN_MULTILEVEL_DEBUGto 1.CAVEATS
You can’t use this module to return across implicit function calls, such as signal handlers (like
$SIG{ALRM}) or destructors (sub DESTROY { ... }). These are invoked automatically by perl and not part of the normal call chain.AUTHORS
COPYRIGHT AND LICENSE
This software is copyright (c) 2013,2014,2021 by Lukas Mai.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.