An exception object describes an exceptional situation. To bring that description to the attention of the user or to handle the situation programmatically, the first step is to raise the exception.
Raise an exception by invoking the current exception handler on
obj. The handler is called with a continuation whose dynamic
environment is that of the call to raise
, except that the current
exception handler is the one that was in place when the handler being
called was installed.
If continuable? is true, the handler is invoked in tail position
relative to the raise-exception
call. Otherwise if the handler
returns, a non-continuable exception of type &non-continuable
is
raised in the same dynamic environment as the handler.
As the above description notes, Guile has a notion of a current exception handler. At the REPL, this exception handler may enter a recursive debugger; in a standalone program, it may simply print a representation of the error and exit.
To establish an exception handler within the dynamic extent of a call,
use with-exception-handler
.
Establish handler, a procedure of one argument, as the current exception handler during the dynamic extent of invoking thunk.
If raise-exception
is called during the dynamic extent of
invoking thunk, handler will be invoked on the argument of
raise-exception
.
There are two kinds of exception handlers: unwinding and non-unwinding.
By default, exception handlers are non-unwinding. Unless
with-exception-handler
was invoked with #:unwind? #t
,
exception handlers are invoked within the continuation of the error,
without unwinding the stack. The dynamic environment of the handler
call will be that of the raise-exception
call, with the
difference that the current exception handler will be “unwound” to the
“outer” handler (the one that was in place when the corresponding
with-exception-handler
was called).
However, it’s often the case that one would like to handle an exception
by unwinding the computation to an earlier state and running the error
handler there. After all, unless the raise-exception
call is
continuable, the exception handler needs to abort the continuation. To
support this use case, if with-exception-handler
was invoked with
#:unwind? #t
is true, raise-exception
will first unwind
the stack by invoking an escape continuation (see call/ec
), and then invoke the handler with the
continuation of the with-exception-handler
call.
Finally, one more wrinkle: for unwinding exception handlers, it can be
useful to Guile if it can determine whether an exception handler would
indeed handle a particular exception or not. This is especially the
case for exceptions raised in resource-exhaustion scenarios like
stack-overflow
or out-of-memory
, where you want to
immediately shrink resource use before recovering. See Stack Overflow. For this purpose, the #:unwind-for-type
keyword
argument allows users to specify the kind of exception handled by an
exception handler; if #t
, all exceptions will be handled; if an
exception type object, only exceptions of that type will be handled;
otherwise if a symbol, only that exceptions with the given
exception-kind
will be handled.