Module /fusion/exception
Operations for working with exceptions.
A Fusion "exception" is any value passed to raise, which in turn invokes the
current exception handler on a thread. While values of any type can be
raised, all exceptions raised by the Fusion runtime and standard library are
subtypes of exn. Thrown exn values include a continuation trace (i.e.,
stack trace) and other information describing the problem.
Exceptions can be understood to have an inheritance hierarchy along these lines:
- any raised value
exn: the base type of all standard exceptionserror_exn: exceptions that indicate runtime errorscontract_error: failure to satisfy the contract of a procedure or syntax formarity_error: a procedure was called with the wrong number of argumentsargument_error: a procedure was called with an invalid argumentresult_error: a procedure returned an invalid result
assertion_error: anassertfailedsyntax_error: a syntax form was used incorrectlyunbound_error: an identifier has no binding
break_exn: the thread was interrupted (not implemented yet)
The various exception types are implicitly constructed and thrown by
corresponding specializations of raise.
Catch exceptions using with_handlers, using predicates to match exceptions
with handlers.
(with_handlers
[(is_result_error (|e| (displayln "A procedure returned a bad result"))),
(is_argument_error (|e| (displayln "A procedure was passed a bad value"))),
(is_error_exn (|e| (displayln "Something else went wrong, rethrowing")
(raise e)))]
(do_something_that_raises))
Exported Bindings
(assert expr message ...)
Evaluates the expr, throwing an exception if the result isn't truthy.
The exception displays the messages, which are only evaluated on failure.
(call_with_handler handler thunk)
Installs the handler then calls the thunk. If raise is called while
the thunk is evaluated, the handler is called with the raised value.
This happens in tail position with respect to call_with_handler.
The handler must be a procedure that accepts one argument: the raised value.
Most code should use the with_handlers syntax form instead of this procedure,
which is prone to error by using a non-thunk body expression.
(is_argument_error v)
Determines whether a value is an exception of type argument_error. Returns true or false.
(is_arity_error v)
Determines whether a value is an exception of type arity_error. Returns true or false.
(is_assertion_error v)
Determines whether a value is an exception of type assertion_error. Returns true or false.
(is_contract_error v)
Determines whether a value is an exception of type contract_error. Returns true or false.
(is_error_exn v)
Determines whether a value is an exception of type error_exn. Returns true or false.
(is_exn v)
Determines whether a value is an exception of type exn.
Returns true or false.
(is_result_error v)
Determines whether a value is an exception of type result_error. Returns true or false.
(is_syntax_error v)
Determines whether a value is an exception of type syntax_error. Returns true or false.
(is_unbound_error v)
Determines whether a value is an exception of type unbound_error. Returns true or false.
(raise value)
Passes the value to the thread's current exception handler. Any type of value
can the raised, but most application code should use the raise_*_error
procedures to raise subtypes of exn.
(raise_argument_error name expected bad_pos value ...+)
Raises an argument_error denoting contract failure due to a procedure being
called with unacceptable argument values.
The name text (string or symbol) identifies the procedure.
The expected string describes the relevant contract.
bad_pos is the zero-based position of the bad argument; a negative value
means that a specific argument is not implicated.
The values are the arguments passed to the procedure.
Note that an argument_error IS-A contract_error.
(raise_arity_error name arity actual_arg ...)
Raises an arity_error denoting contract failure due to a procedure receiving
an unacceptable number of arguments.
The name text (string or symbol) identifies the called procedure.
The arity is an int indicating the expected arity.
The actual_args are the values passed to the procedure.
Note that an arity_error IS-A contract_error.
(raise_contract_error name message)
Raises a contract_error denoting a general contract failure.
The name text (string or symbol) identifies the procedure.
The message string describes the relevant contract failure.
(raise_result_error name expected value)
Raises a result_error denoting contract failure due to a procedure returning
an unacceptable value.
The name text (string or symbol) identifies the calling procedure.
The expected string describes the relevant contract.
The value is the faulty result.
Note that a result_error IS-A contract_error.
(with_handlers ((pred_expr handler_expr) ...) body ...+)
Evaluates each pred_expr (predicate) and handler_expr (handler) in order,
and then the body forms. The predicate and handler expressions must each
return a procedure that accepts one argument: a raised exception value.
If no exceptions are raised during evaluation of the body, then the result of
the with_handlers form is the result of the last body form.
If an exception is raised, then each predicate is applied to the exception
value. Once a predicate returns a truthy value, then the corresponding handler
is applied to the exception, and the handler's result becomes the result of
the entire with_handlers form. If the exception is not matched by any
predicate, then it is re-raised to the continuation of the with_handlers
expression.
Most code should avoid using catch-all predicates like (lambda (x) true) which
match exceptions that should generally not be handled by application code.
In particular, it will catch non-error_exn exceptions like interrupts, which
should pass through unhindered.
See the Racket Guide on Exceptions for more details.