sub try (&@) {
my($try,$catch) = @_;
eval { &$try };
if ($@) {
local $_ = $@;
&$catch;
}
}
sub catch (&) { $_[0] }
try {
die "phooey";
} catch {
/phooey/ and print "unphooey\n";
};
####
package Exception;
use strict;
our ($try, $catch, $prior_catch);
BEGIN {
use Exporter;
our ($VERSION, @ISA, @EXPORT);
$VERSION = "0.04.5";
@ISA = qw(Exporter);
@EXPORT = qw(&try &catch);
*CORE::GLOBAL::die = \¨ # this really should probably be done another
# way or at least be optional.
}
sub die {
my $catch_sub = $catch;
local $catch = $prior_catch;
local $_ = shift;
chomp;
(defined($catch_sub) && $catch_sub ne "" && &$catch_sub) || CORE::die $_;
}
sub catch (&) { }
sub try (&@) {
local $prior_catch = $catch;
{
local ($try, $catch) = @_;
eval { &$try; }
}
&die($@) if $@;
}
return 1;
####
#!/usr/bin/perl
use strict;
use Exception;
sub throw {
my $err = shift;
print "throwing $err\n";
die $err;
}
catch { die "You shouldn't see this.\n"; }; # This would simply be insane
try {
throw "foo";
try {
throw "bar";
throw "baz";
print "You should NOT see this line, baz was fatal to this block.\n";
} catch {
/^bar/ and do {
print "$_ caught and trapped\n";
return 1; # one means exception is "trapped".
# unlike using eval, the execution continues
# in the block that threw the exception
};
/^baz/ and do {
print "$_ caught, but we won't trap it here\n";
return 0; # zero means "untrapped". Even though we
# can do some processing here, we'll propagate
# the exception "outward"
};
};
throw "quux";
print "The outer try block completed successfully\n";
} catch {
/^foo/ and do {
print "$_ caught\n";
return 1;
};
/^baz/ and do {
print "Caught $_ in outer catch, we'll trap it now\n";
return 1;
};
/^quux/ and do {
print "$_ caught\n";
try {
throw "quuux within quux's catch!";
} catch {
/^quuux/ and do {
print "$_ caught.\n";
return 1;
};
};
return 1;
};
};
print "\n";
print "Done testing logic!\n";