catch exceptions hook, line, and sinker.
:deps {io.github.noahtheduke/sinker {:mvn/version "0.1.0"}}
it's try
but a little nicer:
(require '[noahtheduke.sinker :as sinker :refer [try+]])
;; works like normal try
(try+)
;; => nil
(try+ 1 2 3)
;; => 3
(try+ (throw (Exception. "hello world!"))
(catch Exception ex
(ex-message ex)))
;; => "hello world!"
;; ex-infos with `:noahtheduke.sinker/type` (or `:type`) ex-data can be caught with a keyword.
;; the keywords are compared with isa? to respect heirarchies.
;; the bound variable is the ex-data, not the exception itself.
(try+ (throw (ex-info "Wrong parameter" {::sinker/type :invalid-parameter
:expected :abc
:given :foobar}))
(catch :invalid-parameter data
(:given data)))
;; => :foobar
;; the exception is on the metadata of the bind under the key `:noahtheduke.sinker/exception`.
(try+ (throw (ex-info "Wrong parameter" {::sinker/type :invalid-parameter
:expected 'abc
:given 'foobar}))
(catch :invalid-parameter data
(ex-message (:noahtheduke.sinker/exception (meta data)))))
;; => "Wrong parameter"
;; because the ex-data is a map, it can be destructured
(try+ (throw (ex-info "Wrong parameter" {::sinker/type :invalid-parameter
:expected :abc
:given :foobar}))
(catch :invalid-parameter {:keys [expected given]}
[expected given (= expected given)]))
;; => [:abc :foobar false]
;; ex-infos can also be caught with predicate functions or vars.
;; the predicate must be a 1-arg function that takes the `ex-data`.
;; like catching a keyword, the bound variable is the ex-data, not the exception itself.
(defn pred [data]
(= :value (:key data)))
(try+ (throw (ex-info "KV pair" {::sinker/type :incorrect-argument
:key :value}))
(catch pred {k :key}
k))
;; => :value
;; like normal try, each catch is checked in definition order,
;; and finally clauses gotta come last
(defn pred2 [data]
(= :value2 (:key2 data)))
(def finally-ran? (atom nil))
(try+ (assert (= 1 2) "This will work")
(catch :invalid-argument _
:invalid-argument)
(catch pred2 ex
(ex-message ex))
(catch clojure.lang.ExceptionInfo ex
(ex-data ex))
(catch Exception _
"Got us an exception!")
(catch Throwable t
(str "Received a " (.getName (class t))))
(finally
(reset! finally-ran? "hoodee hoodee hoo")))
;; => "Received a java.lang.AssertionError"
@finally-ran?
;; => "hoodee hoodee hoo"
this library is quite similar to exoscale/ex
, but ex
is solely focused on exception infos and does a lot more, with a stronger emphasis on a specific pattern of error handling. i wrote this to fill a gap in lazytest and to satisfy my curiosity. i don't expect this to receive widespread adoption nor do i really want it. sometimes it's just nice to make something and let others check it out, you know?
Copyright © Noah Bogart
Distributed under the Mozilla Public License version 2.0.
Can you improve this documentation?Edit at git repository
cljdoc builds & hosts documentation for Clojure/Script libraries
Ctrl+k | Jump to recent docs |
← | Move to previous article |
→ | Move to next article |
Ctrl+/ | Jump to the search field |