Exception::Resumable -- resumable exceptions for Perl.
use Exception::Resumable; handle { ... raise $exception, @args; ... } exception_1 => sub { ...; return $value_to_use }, qr/exception_2/ => sub { ...; raise $new_exception, @args }, [qw(exception_3 exception_4)] => $value_to_use, { exception_5 => 1, exception_6 => 1 } => sub { ... };
This module implements a basic version of "resumable exceptions." This means that a dynamically-bound handling function is called before the stack is unwound, rather than afterwards (like die). The appropriate handler is found by looking (in order) at @Exception::Resumable::CATCH. If no appropriate handler is found, die is called instead.
die
@Exception::Resumable::CATCH
Why would you want to do this? Perl's standard eval/die exception handling limits what you can do when something goes wrong: by the time you get control again after something dies, the stack has already been unwound to your eval. If you want to fix the problem and continue, you have to get back to where the code died.
eval/die
eval
Sometimes this is fine: if your web server encountered a network error, you probably want to clean up the connection and wait for the user to hit "reload." However, sometimes it's easier to fix the problem right there and keep going: if a function receives invalid input, you may want to ask the user for a better answer and continue.
handle BLOCK HANDLERS...
Handle exceptions from within BLOCK using HANDLERS, a list of key/value pairs. The handlers defined by a handle block are not active while they are called, so re-raising the same exception will not cause an infinite loop. A handler value may be either a function, which will be called with the arguments passed to raise, or a scalar, which will be returned as-is.
BLOCK
HANDLERS
handle
raise
On Perls older than 5.10, the key may be one of the following:
\@ARRAY
Catch the exception if it is (eq to) a member of @ARRAY.
eq
@ARRAY
\%HASH
Catch the exception if it is a key in %HASH.
%HASH
qr/REGEXP/
Catch the exception if it matches REGEXP.
REGEXP
$SCALAR
Catch the exception if it is eq to $SCALAR.
On Perl 5.10 and newer, the key may be any scalar that can go on the right side of a "smart match".
raise NAME, DETAILS...
Raise exception NAME with detailed information DETAILS.
NAME
DETAILS
test_raise NAME
See what would happen if you raise NAME. Return the $key, $value that would have handled NAME, or undef if it would have died.
$key, $value
undef
Say you have a program that watches some log files. If one of the files disappears all of a sudden, and it is running interactively, it can ask the user to point it in the right direction. If not, it should just die:
sub process_file { my $file = shift; if (!-f $file) { $file = raise "Missing file", $file; } # do stuff, now that we know $file is valid } sub get_a_file { print "Use what for $_[0]? "; chomp(my $f = <STDIN>); $f = raise "Missing file", $f unless -f $f; $f; } sub main { handle { # stuff that calls process_file } is_interactive() ? ('Missing file' => \&get_a_file) : (); }
Exception::* (and especially Try::Tiny) on CPAN, for many, many flavors of exception handling. Writing exception modules seems almost as popular as writing test modules, sudoku solvers, and Fibonacci functions.
Exception::*
See also the Common Lisp Hyperspec section 9.1, "Condition System Concepts" and Common Lisp the Language's section 29, "Conditions." Both are available online, and describe the error-handling model partially emulated here.
Sean O'Rourke, <seano@cpan.org>
Bug reports welcome, patches even more welcome.
Copyright (C) 2007-2011 Sean O'Rourke. All rights reserved, some wrongs reversed. This module is distributed under the same terms as Perl itself.
To install Exception::Resumable, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Exception::Resumable
CPAN shell
perl -MCPAN -e shell install Exception::Resumable
For more information on module installation, please visit the detailed CPAN module installation guide.