No longer in developement, if you want the same ideas with way better implementation, head to exoscale/ex
An exception library, drop in replacement for try
/catch
/finally
,
that adds support for ex-info
/ex-data
with a custom (clojure)
hierarchy that allows to express exceptions relations.
So we have qbits.ex/try+
, which supports vanilla catch
/finally
clauses.
If you specify a catch-data
clause with a keyword as first argument
things get interesting. We assume you always put a :type
key in the
ex-info you want to use with this, and will match its value to the
value of the key in the catch-data
clause.
Essentially catch-data
takes this form:
(catch-data :something m
;; where m is a binding to the ex-data (you can destructure at that level as well)
)
So you can do things like that.
(require '[qbits.ex :as ex])
(ex/try+
(throw (ex-info "Argh" {:type ::bar :foo "a foo"}))
(catch-data ::foo data
(prn :got-ex-data data))
(catch-data ::bar {:as data :keys [foo]}
;; in that case it would hit this one
(prn :got-ex-data-again foo))
(catch ExceptionInfo e
;; this would match an ex-info that didn't get a hit with catch-ex-info)
(catch Exception e (prn :boring))
(finally (prn :boring-too)))
But there's a twist.
I thought leveraging a clojure hierarchy could make sense in that context too, so you can essentially create exceptions hierachies without having to mess with Java classes directly and in a clojuresque" way.
;; so bar is a foo
(ex/derive ::bar ::foo)
(ex/try+
(throw (ex-info "I am a bar" {:type ::bar})
(catch-data ::foo d
(prn "got a foo with data" d)
(prn "Original exception instance is " (-> d meta ::ex/exception))))
You can also get the full exception instance via the metadata on the
ex-data we extract, it's under the :qbits.ex/exception
key.
Some real life examples of usage for this:
-
make some exceptions end-user exposable in http responses via an error middleware in a declarative way .
-
skip sentry logging for some kind of exceptions (or the inverse)
-
make an exception hierachy for our query language type of errors for specialized reporting per "type"
Other than that it's largely inspired by
catch-data, the
implementation is slightly different, we dont catch Throwable, we
instead generate a catch clause on clj ex-info
and generate a cond
that tries to match ex-data with the :type key using isa?
with our
hierarchy, which arguably is closer to I would write by hand in that
case.
ex is available on Clojars.
Add this to your dependencies:
or you can just grab it via deps.edn
directly
Copyright © 2018 Max Penet
Distributed under the Eclipse Public License, the same as Clojure.