catch evaluates an expression and handles any thrown exception that matches
one of its branches.
Syntax
(catch ⟨expr⟩
((⟨exception-ctor⟩ ⟨pattern⟩ ...) ⟨handler-body⟩ ...)
((the ⟨exception-type⟩ ⟨var-or-_⟩) ⟨handler-body⟩ ...)
...
(_ ⟨fallback-body⟩ ...))
Semantics
- The first subform is the expression that may throw.
- Each branch matches an exception constructor pattern, every exception of a
given type, or
_as a catch-all. - A branch written
(the ⟨exception-type⟩ var)catches any exception of that type and binds it tovar, which can be rethrown withthrow. For a native exception (seedefine-exception), this includes conditions of Lisp subtypes of its condition type. - A
_branch catches every Lisperror, including Coalton exceptions and panics. A(the coalton/exception:LispError e)branch catches the same errors and binds them. A(the Panic p)branch catches only panics, the errors signaled byerror,unwrap,unreachable, and failedasserts. - Patterns are tried in order, including patterns on constructor fields, at the point where the exception was thrown. The first matching branch is selected. If none matches, the exception propagates to enclosing handlers without unwinding anything.
- Once a branch is selected, control unwinds to the
catchexpression and the branch runs there. It sees the dynamic bindings of thecatchrather than those of the code that threw, it is in tail position when thecatchis, and exceptions it throws are not caught by the samecatch. - Because the branch runs after unwinding, it cannot
resume-toa resumption established inside the guarded expression. Usehandlefor that. - All branches must agree on the result type of the
catchexpression.
Example
(define (crack-safely egg)
(catch (Ok (crack egg))
((DeadlyEgg _) (Err (DeadlyEgg egg)))
((UnCracked _) (Err (UnCracked egg)))))
(define (crack-or-rethrow egg)
(catch (crack egg)
((the BadEgg e)
(trace "bad egg")
(throw e))))