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;