Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 28 additions & 14 deletions doc/Language/exceptions.pod6
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ problem.

=head1 Catching exceptions

It's possible to handle exceptional circumstances by supplying a C<CATCH> block:
It's possible to handle exceptional circumstances by supplying a
C<CATCH> block:

die X::IO::DoesNotExist.new(:path("foo/bar"), :trying("zombie copy"));

Expand All @@ -57,18 +58,22 @@ It's possible to handle exceptional circumstances by supplying a C<CATCH> block:

# OUTPUT: «some kind of IO exception was caught!»

Here, we are saying that if any exception of type C<X::IO> occurs, then the
message C<some kind of IO exception was caught!> will be sent to I<stderr>,
which is what C<$*ERR.say> does, getting displayed on whatever constitutes the
standard error device in that moment, which will probably be the console by
default.
Here, we are saying that if any exception of type C<X::IO> occurs, then
the message C<some kind of IO exception was caught!> will be sent to
I<stderr>, which is what C<$*ERR.say> does, getting displayed on
whatever constitutes the standard error device in that moment, which
will probably be the console by default.

A X<C<CATCH>|CATCH> block uses smartmatching similar to how C<given/when>
smartmatches on options, thus it's possible to catch and handle various
categories of exceptions inside a C<when> block.
Note that the match target is a role. To allow user defined exceptions
to match in the same manner, they must implement the given role. Just
existing in the same namespace will make them look alike but won't match
in a C<CATCH> block.

To handle all exceptions, use a C<default> statement. This example prints out
almost the same information as the normal backtrace printer.
A C<CATCH> block places any exception thrown in its topic variable
(C<$_>), thus it's possible to catch and handle various categories of
exceptions inside a C<when> block. To handle all exceptions, use a
C<default> statement. This example prints out almost the same
information as the normal backtrace printer:

CATCH {
default {
Expand All @@ -81,9 +86,18 @@ almost the same information as the normal backtrace printer.
}
}

Note that the match target is a role. To allow user defined exceptions to match
in the same manner, they must implement the given role. Just existing in the
same namespace will look alike but won't match in a C<CATCH> block.
While this is a very common pattern, it is not strictly necessary to use
C<default> or C<when> in a C<CATCH> block. This is done to prevent the
control flow from reaching the end of the block where, unless the
exception has been L<resumed|#Resuming_of_exceptions>, the exception
will continue to be thrown. Allowing this can be used for logging
purposes, for instance:

=for code :skip-test<creates a file>
# In the outermost block of a script...
my IO::Handle:D $log = open sprintf('logs/%d-%d.txt', $*INIT-INSTANT, $*PID), :a;
CATCH { $log.printf: "[%d] Died with %s: %s$?NL", now, .^name, .message }
END { $log.close }

=head2 Exception handlers and enclosing blocks

Expand Down