Exceptions¶
An error in a form arrives as an exception, and try decides which ones you
catch. Errors is the message you see when nothing does.
catch names a class, and there are three:
| Class | Catches |
|---|---|
Exception |
Any error, including ExceptionInfo |
ExceptionInfo |
An error from ex-info |
Throwable |
Any error, and stack overflow |
(try
(throw (ex-info "arm too far" {:angle 95}))
(catch ExceptionInfo e (ex-data e)) ; => {:angle 95.0}
(catch Exception e (ex-message e))) ; any other error
The first matching catch wins, so ExceptionInfo comes before Exception:
Exception would catch the ex-info error too.
ex-info takes a message and a map, ex-message returns the message, and
ex-data returns the map:
user=> (try (throw (ex-info "boom" {:code 7}))
(catch ExceptionInfo e [(ex-message e) (ex-data e)]))
["boom" {:code 7.0}]
finally¶
finally runs whichever way the body leaves: with a value, with a caught error,
or with one that nothing catches:
user=> (try (throw (ex-info "boom" {:code 7})) (finally (println "cleanup")))
cleanup
Execution error: boom
Nothing cuts a finally short, so it is the place to undo what the body did. In
a loop it runs when the loop stops, by (control/stop), by STOP or by an error;
see Control Loops.
recur and try¶
recur cannot be wrapped in a try, so a loop that catches must keep the try
inside one round:
user=> (loop [i 0] (when (< i 3) (try (println i)) (recur (inc i))))
0.0
1.0
2.0
nil
The other way round is a syntax error:
user=> (loop [] (try (recur)))
Syntax error: Can only recur from tail position