Previous: Threads, Up: Program structure [Contents][Index]
An exception is an object used to signal an error or other exceptional situation. The program or run-time system can throw the exception when an error is discovered. An exception handler is a program construct that registers an action to handle exceptions when the handler is active.
If an exception is thrown and not handled then the read-eval-print-loop will print a stack trace, and bring you back to the top level prompt. When not running interactively, an unhandled exception will normally cause Kawa to be exited.
In the Scheme exception model (as of R6RS and R7RS), exception handlers are one-argument procedures that determine the action the program takes when an exceptional situation is signaled. The system implicitly maintains a current exception handler in the dynamic environment. The program raises an exception by invoking the current exception handler, passing it an object encapsulating information about the exception. Any procedure accepting one argument can serve as an exception handler and any object can be used to represent an exception.
The Scheme exception model is implemented on top of the Java VM’s
native exception model where the only objects that
can be thrown are instances of java.lang.Throwable
.
Kawa also provides direct access to this native model,
as well as older Scheme exception models.
It is an error if handler does not accept one argument.
It is also an error if thunk does not accept zero arguments.
The with-exception-handler
procedure returns the results
of invoking thunk. The handler is installed as the current
exception handler in the dynamic environment used for the
invocation of thunk.
(call-with-current-continuation (lambda (k) (with-exception-handler (lambda (x) (display "condition: ") (write x) (newline) (k 'exception)) (lambda () (+ 1 (raise ’an-error)))))) ⇒ exception and prints condition: an-error
(with-exception-handler (lambda (x) (display "something went wrong\n")) (lambda () (+ 1 (raise ’an-error)))) prints something went wrong
After printing, the second example then raises another exception.
Performance note: The thunk is inlined if it is a
lambda expression. However, the handler cannot be inlined
even if it is a lambda expression, because it could be called by
raise-continuable
. Using the guard
form is
usually more efficient.
Raises an exception by invoking the current exception handler on obj. The handler is called with the same dynamic environment as 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 the handler returns, then obj is re-raised in the same dynamic environment as the handler.
If obj is an instance of java.lang.Throwable
,
then raise
has the same effect as primitive-throw
.
Raises an exception by invoking the current exception handler on obj.
The handler is called with the same dynamic
environment as the call to raise-continuable
, except
that: (1) the current exception handler is the one that was
in place when the handler being called was installed, and
(2) if the handler being called returns, then it will again
become the current exception handler.
If the handler returns, the values it returns become the values
returned by the call to raise-continuable
.
(with-exception-handler (lambda (con) (cond ((string? con) (display con)) (else (display "a warning has been issued"))) 42) (lambda () (+ (raise-continuable "should be a number") 23))) prints: should be a number ⇒ 65
The body is evaluated with an exception handler that binds
the raised object to variable and, within the scope of that binding,
evaluates the clauses as if they were the clauses of a cond
expression.
That implicit cond
expression is evaluated with
the continuation and dynamic environment of the guard
expression. If every cond-clause’s test evaluates to #f
and there is no else
clause, then raise-continuable
is
invoked on the raised object within the dynamic environment of the
original call to raise
or raise-continuable
,
except that the current exception handler is that of the
guard
expression.
(guard (condition ((assq 'a condition) => cdr) ((assq 'b condition))) (raise (list (cons 'a 42)))) ⇒ 42
(guard (condition ((assq 'a condition) => cdr) ((assq 'b condition))) (raise (list (cons 'b 23)))) ⇒ (b . 23)
Performance note: Using guard
is moderately efficient:
there is some overhead compared to using native exception handling,
but both the body and the handlers in the cond-clause
are inlined.
All three arguments must be 0-argument procedures. First calls in-guard, then thunk, then out-guard. The result of the expression is that of thunk. If thunk is exited abnormally (by throwing an exception or invoking a continuation), out-guard is called.
If the continuation of the dynamic-wind is re-entered (which is not yet possible in Kawa), the in-guard is called again.
This function was added in R5RS.
Returns #t if obj is an object raised by the read
procedure.
(That is if obj is a gnu.text.SyntaxException
.)
Returns #t if obj is an object raised by inability to open an input
or output port on a file.
(This includes java.io.FileNotFoundException
as well
as certain other exceptions.)
Raises an exception as if by calling raise
on a newly allocated simple error object,
which encapsulates the information provided by message
(which should a string), as well as any obj arguments,
known as the irritants.
The string representation of a simple error object is as if calling
(format "#<ERROR ~a~{ ~w~}>" message irritants)
.
(That is the message is formatted as if with display
while each irritant obj is formatted as if with write
.)
This procedure is part of SRFI-23, and R7RS.
It differs from (and is incompatible with) R6RS’s error
procedure.
Returns #t
if obj is a simple error object.
Specifically, that obj is an instance of kawa.lang.NamedException
.
Otherwise, it returns #f
.
Returns the message encapsulated by error-object, which must be a simple error object.
Returns a list of the irritants (other arguments) encapsulated by error-object, which must be a simple error object.
These functions associate a symbol with exceptions and handlers: A handler catches an exception if the symbol matches.
Invoke thunk in the dynamic context of handler for exceptions matching key. If thunk throws to the symbol key, then handler is invoked this way:
(handler key args ...)
key may be a symbol. The thunk takes no
arguments. If thunk returns normally, that is the return value of
catch
.
Handler is invoked outside the scope of its own catch
. If
handler again throws to the same key, a new handler from further
up the call chain is invoked.
If the key is #t
, then a throw to any symbol will match
this call to catch
.
Invoke the catch form matching key, passing the args to the current handler.
If the key is a symbol it will match catches of the same
symbol or of #t
.
If there is no handler at all, an error is signaled.
Throws the exception, which must be an instance of a sub-class
of java.lang.Throwable
.
Evaluate body, and return its result. However, before it returns, evaluate handler. Even if body returns abnormally (by throwing an exception), handler is evaluated.
(This is implemented just like Java’s try
-finally
.
However, the current implementation does not duplicate the handler.)
Evaluate body, in the context of the given handler specifications. Each handler has the form:
var type exp ...
If an exception is thrown in body, the first handler is selected such that the thrown exception is an instance of the handler’s type. If no handler is selected, the exception is propagated through the dynamic execution context until a matching handler is found. (If no matching handler is found, then an error message is printed, and the computation terminated.)
Once a handler is selected,
the var is bound to the thrown exception, and the exp in
the handler are executed. The result of the try-catch
is the result of body if no exception is thrown, or the
value of the last exp in the selected handler if an
exception is thrown.
(This is implemented just like Java’s try
-catch
.)
Previous: Threads, Up: Program structure [Contents][Index]