···13it's `try` but a little nicer:
1415```clojure
16-(require '[noahtheduke.sinker :refer [try+]])
1718;; works like normal try
00019(try+ 1 2 3)
20;; => 3
21···24 (ex-message ex)))
25;; => "hello world!"
2627-;; ex-infos with `:type` ex-data can be caught with a keyword.
28;; the keywords are compared with isa? to respect heirarchies.
29;; the bound variable is the ex-data, not the exception itself.
30-(try+ (throw (ex-info "Wrong parameter" {:type :invalid-parameter
31 :expected :abc
32 :given :foobar}))
33 (catch :invalid-parameter data
···35;; => :foobar
3637;; the exception is on the metadata of the bind under the key `:noahtheduke.sinker/exception`.
38-(try+ (throw (ex-info "Wrong parameter" {:type :invalid-parameter
39 :expected 'abc
40 :given 'foobar}))
41 (catch :invalid-parameter data
···43;; => "Wrong parameter"
4445;; because the ex-data is a map, it can be destructured
46-(try+ (throw (ex-info "Wrong parameter" {:type :invalid-parameter
47 :expected :abc
48 :given :foobar}))
49 (catch :invalid-parameter {:keys [expected given]}
···56(defn pred [data]
57 (= :value (:key data)))
5859-(try+ (throw (ex-info "KV pair" {:type :incorrect-argument
60 :key :value}))
61- (catch pred data
62- (:key data)))
63;; => :value
6465;; like normal try, each catch is checked in definition order,
66;; and finally clauses gotta come last
67(defn pred2 [data]
68 (= :value2 (:key2 data)))
69-(def errored? (atom nil))
07071(try+ (assert (= 1 2) "This will work")
72 (catch :invalid-argument _
···80 (catch Throwable t
81 (str "Received a " (.getName (class t))))
82 (finally
83- (reset! errored? "hoodee hoodee hoo")))
84;; => "Received a java.lang.AssertionError"
8586-@errored?
87;; => "hoodee hoodee hoo"
88```
00000008990## license
91
···13it's `try` but a little nicer:
1415```clojure
16+(require '[noahtheduke.sinker :as sinker :refer [try+]])
1718;; works like normal try
19+(try+)
20+;; => nil
21+22(try+ 1 2 3)
23;; => 3
24···27 (ex-message ex)))
28;; => "hello world!"
2930+;; ex-infos with `:noahtheduke.sinker/type` (or `:type`) ex-data can be caught with a keyword.
31;; the keywords are compared with isa? to respect heirarchies.
32;; the bound variable is the ex-data, not the exception itself.
33+(try+ (throw (ex-info "Wrong parameter" {::sinker/type :invalid-parameter
34 :expected :abc
35 :given :foobar}))
36 (catch :invalid-parameter data
···38;; => :foobar
3940;; the exception is on the metadata of the bind under the key `:noahtheduke.sinker/exception`.
41+(try+ (throw (ex-info "Wrong parameter" {::sinker/type :invalid-parameter
42 :expected 'abc
43 :given 'foobar}))
44 (catch :invalid-parameter data
···46;; => "Wrong parameter"
4748;; because the ex-data is a map, it can be destructured
49+(try+ (throw (ex-info "Wrong parameter" {::sinker/type :invalid-parameter
50 :expected :abc
51 :given :foobar}))
52 (catch :invalid-parameter {:keys [expected given]}
···59(defn pred [data]
60 (= :value (:key data)))
6162+(try+ (throw (ex-info "KV pair" {::sinker/type :incorrect-argument
63 :key :value}))
64+ (catch pred {k :key}
65+ k))
66;; => :value
6768;; like normal try, each catch is checked in definition order,
69;; and finally clauses gotta come last
70(defn pred2 [data]
71 (= :value2 (:key2 data)))
72+73+(def finally-ran? (atom nil))
7475(try+ (assert (= 1 2) "This will work")
76 (catch :invalid-argument _
···84 (catch Throwable t
85 (str "Received a " (.getName (class t))))
86 (finally
87+ (reset! finally-ran? "hoodee hoodee hoo")))
88;; => "Received a java.lang.AssertionError"
8990+@finally-ran?
91;; => "hoodee hoodee hoo"
92```
93+94+## others in the space
95+96+- [exoscale/ex](https://github.com/exoscale/ex)
97+- [scgilardi/slingshot](https://github.com/scgilardi/slingshot/)
98+99+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](https://github.com/NoahTheDuke/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?
100101## license
102
+1-1
src/noahtheduke/sinker.clj
···58 [t ex-info? data catch-clauses]
59 (for [{:keys [type pred id body]} catch-clauses]
60 (case type
61- :catch/type `[(and ~ex-info? (isa? ~pred (:type ~data)))
62 (let [data# (or (ex-data ~t) {})
63 ~id (vary-meta data# assoc ::exception ~t)]
64 ~@body)]