NAME
Worlogog::Restart - Lisp-style dynamic restarts
SYNOPSIS
use Worlogog::Restart -all => { -prefix => 'restart_' };
my $x = restart_case {
restart_invoke 'foo', 21;
die; # not reached
} {
foo => sub {
return $_[0] * 2;
},
};
print "$x\n"; # 42
my $y = restart_bind {
my $x = restart_invoke 'bar', 20;
return $x + 2;
} {
bar => sub {
return $_[0] * 2;
},
};
print "$y\n"; # 42
DESCRIPTION
This module provides dynamic restarts similar to those found in Common Lisp. A restart is a bit like an exception handler or a dynamically scoped function. It can be invoked (by name) from any subroutine call depth as long as the restart is active.
Functions
The following functions are available:
- invoke RESTART
- invoke RESTART, ARGUMENTS
-
Invokes RESTART, passing it ARGUMENTS (if any) in
@_
. Returns whatever RESTART returns (provided it returns normally, which restarts established bycase
never do).RESTART can be either a restart object (such as those returned by
find
orcompute
) or a restart name (a string). Names are looked up dynamically by searching outwards through all handlers established bybind
orcase
. If no matching restart is found, this is an error andinvoke
die
s. - bind BLOCK HASHREF
-
Executes BLOCK with the restarts specified by HASHREF, which maps restart names (strings) to handlers (subroutine references). Returns whatever BLOCK returns.
- case BLOCK HASHREF
-
Executes BLOCK with the restarts specified by HASHREF, which maps restarts names (strings) to handlers (subroutine references). Returns whatever BLOCK returns (or what the corresponding restart returns if
invoke
is used to return fromcase
).Unlike
bind
, the restarts it establishes always unwind the stack first before running and thus ultimately return fromcase
itself, not frominvoke
. That is, a restart established bycase
will implicitly return from all subroutines betweencase
andinvoke
, then execute the handler body specified in HASHREF, then return fromcase
. - find RESTART
-
Finds the restart that would be called by
invoke
at this point. Returns a restart object representing the restart orundef
if no corresponding restart is active. RESTART must be a name (string).Restart objects returned by
find
have the following methods: - compute
-
Searches outwards and returns a list of restart objects representing all currently active restarts. The innermost restarts will be listed first.
The returned list may contain restarts that you can't normally invoke because they're shadowed by a more recent restart with the same name:
# prints "9" because the innermost 'foo' is listed first print bind { bind { my @restarts = compute; # # $restarts[0]->name = 'foo' # $restarts[0]->code = sub { $_[0] + 2 } # # $restarts[1]->name = 'foo' # $restarts[1]->code = sub { $_[0] * 3 } my $x = 1; $x = invoke($_, $x) for @restarts; # $x = $x + 2 # $x = $x * 3 $x } { foo => sub { $_[0] + 2 }, }; } { foo => sub { $_[0] * 3 }, };
This module uses Exporter::Tiny
, so you can rename the imported functions at use
time.
SEE ALSO
Exporter::Tiny, Return::MultiLevel
AUTHOR
Lukas Mai, <l.mai at web.de>
COPYRIGHT & LICENSE
Copyright 2013, 2014 Lukas Mai.
This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.