Errors and Conditions
Raise, catch, group and re-raise errors in ELPS with error, handler-bind, define-condition and rethrow.
An ELPS error has a condition, a symbol that names its kind, and data. (error 'not-found "no claim" id) raises the condition not-found with the data "no claim" and id. The Language Guide shows the basics. This page shows how to group conditions, which handler runs, and how to re-raise an error with more context.
Every example on this page runs in your browser. Edit an example to see the new result.
Catch an error
handler-bind binds a handler function to each condition. When the body raises one of them, the handler runs and its value is the value of handler-bind. The handler gets the condition and the data.
A binding for condition catches every error. Do not use it to hide errors you did not expect.
Group conditions
(define-condition 'child 'parent) gives a condition a parent. A handler for the parent then catches the child too. Define the parents first.
ELPS gives three built-in conditions the parent error: argument-error (a bad argument to a builtin), match-error (a value that does not fit a binding pattern) and record-error (a broken record rule).
When more than one binding matches, the most specific one runs: the binding for the condition itself, then for its nearest parent, and condition last. The order you write the bindings in does not matter.
(condition-is? 'claim-closed 'claim-error) returns true.
Re-raise an error
To log an error and let it continue, call (rethrow) in the handler. rethrow keeps the original stack and data. (apply error c data) loses the stack, so do not use it.
(rethrow :context "text") adds text in front of the message, as Go's fmt.Errorf("text: %w", err) does. The condition and the data do not change, so outer handlers still match. (error-message) in a handler returns the message with its context.
Clean up after an error
with-cleanup runs cleanup forms when its body ends, also when the body raises an error. It is the finally of other languages. See with-cleanup.
ignore-errors returns () for any error. It hides mistakes, so use handler-bind with named conditions where you can.