Error Handling
Libraries: slingshot (throw+/try+ with arbitrary data), failjure (monadic error handling), cognitect anomalies (a standard vocabulary of error categories: :cognitect.anomalies/not-found, /unavailable, /incorrect, ...).
;; try / catch / finally
(try
(/ 1 0)
(catch ArithmeticException e
(println "Math error:" (.getMessage e))
:div-by-zero)
(catch Exception e
(println "Other error" e))
(finally
(println "cleanup")))
;; ex-info: exceptions carrying data (the idiomatic Clojure way)
(defn withdraw [balance amount]
(when (> amount balance)
(throw (ex-info "Insufficient funds"
{:type ::insufficient-funds :balance balance :requested amount})))
(- balance amount))
(try
(withdraw 50 100)
(catch clojure.lang.ExceptionInfo e
(let [{:keys [type balance requested]} (ex-data e)]
(println (ex-message e) "- short by" (- requested balance)))))
(ex-cause e) ; the wrapped cause
(Throwable->map e) ; data view of an exception (with :via, :trace, :cause)
;; with-open: resource management (calls .close)
(with-open [rdr (clojure.java.io/reader "data.txt")]
(count (line-seq rdr)))
;; Returning errors as data (an alternative to exceptions)
(defn parse-age [s]
(if-let [n (parse-long s)]
(if (<= 0 n 150) {:ok n} {:error :out-of-range :value n})
{:error :not-a-number :value s}))
(parse-age "42")
…