Failures and Soft Errors

When to use what: fail for expected, recoverable errors in library functions (callers choose to check or let it throw); die for exceptional conditions and bugs.

use fatal; makes Failures throw immediately within a lexical scope.

# fail returns an unthrown exception (a Failure): it explodes only if used carelessly
sub parse-int(Str $s) {
    return $s.Int if $s ~~ /^ '-'? \d+ $/;
    fail "Not an integer: '$s'";
}

my $good = parse-int('42');
my $bad  = parse-int('abc');

say $good + 1;                         # 43
say $bad.defined;                      # False (checking definedness or truthiness "handles" the Failure)
with parse-int('xyz') { say "Parsed $_" } else { say "Failed: {.exception.message}" }
say parse-int('7') // 0;               # 7
say parse-int('?') // 0;               # 0 (// handles the Failure)
# say $bad + 1;                        # this would throw: the Failure is "used"

# Built-ins that return Failures
my $n = 'abc'.Int;                     # Failure (X::Str::Numeric)
say $n.so;                             # False
my $fh = open 'missing-file.txt';      # Failure (doesn't throw until used)
say "can't open" unless $fh;

# Unhandled Failures throw when they're sunk (discarded) or used
# 'abc'.Int;                           # would throw when sunk

# orelse / andthen chains
my $value = parse-int('oops') orelse 'default';
say $value;                            # default
parse-int('10') and
…