Exceptions
# Throwing
die "Something went wrong"; # X::AdHoc
die X::OutOfRange.new(what => 'Index', got => 10, range => 0..5);
# Catching with try
my $result = try { die "oops"; 42 };
say $result.raku; # Nil
say $!.message; # oops
# CATCH blocks (inside any block) with when clauses
sub risky($n) {
die X::AdHoc.new(payload => "negative: $n") if $n < 0;
die X::OutOfRange.new(what => 'n', got => $n, range => 0..100) if $n > 100;
$n
}
for -1, 50, 200 -> $n {
risky($n).say;
CATCH {
when X::OutOfRange { say "Out of range: {.message}" }
when X::AdHoc { say "Ad hoc: {.message}" }
default { say "Other: {.^name}" }
}
}31.1 Custom Exceptions
class X::Bank::InsufficientFunds is Exception {
has $.needed;
has $.available;
method message { "Insufficient funds: need $!needed, have $!available" }
}
sub withdraw($balance, $amount) {
X::Bank::InsufficientFunds.new(needed => $amount, available => $balance).throw
if $amount > $balance;
$balance - $amount
}
try {
withdraw(50, 100);
CATCH {
when X::Bank::InsufficientFunds {
say .message;
say "Short by {.needed - .available}";
}
}
}31.2 Resuming, Rethrowing and Warnings
Common built-in exceptions: X::AdHoc, X::TypeCheck, X::OutOfRange, X::Str::Numeric, X::Method::NotFound, X::IO::DoesNotExist, X::Multi::NoMatch, X::Syntax::*, X::Promise::Broken.
# Resumable exceptions: warnings and control exceptions can resume
{
warn "low disk space"; # a resumable warning (CX::Warn)
say "continuing after the warning";
CONTROL { when CX::Warn { note "WARN: {.message}"; .resume } }
}
# Rethrow
try { # outer try catches the rethrown exception
{
die "inner";
CATCH { default { note "logging: {.message}"; .rethrow } }
}
}
say "caught again: $!" if $!;
# quietly suppresses warnings
quietly { warn "ignored" };
# .backtrace, .message, .gist on exception objects
try { die "trace me" }; say $!.backtrace.Str.lines.head;