merr
merr copied to clipboard
:fire: Minimal and good enough error handling library for Clojure/ClojureScript
= merr
image:https://github.com/liquidz/merr/workflows/test/badge.svg["GitHub Actions for test workflow", link="https://github.com/liquidz/merr/actions?query=workflow%3Atest"] image:https://github.com/liquidz/merr/workflows/lint/badge.svg["GitHub Actions for lint workflow", link="https://github.com/liquidz/merr/actions?query=workflow%3Alint"] image:https://github.com/liquidz/merr/workflows/dependencies/badge.svg["GitHub Actions for dependencies workflow", link="https://github.com/liquidz/merr/actions?query=workflow%3Adependencies"] image:https://codecov.io/gh/liquidz/merr/branch/master/graph/badge.svg["codecov", link="https://codecov.io/gh/liquidz/merr"]
image:https://img.shields.io/clojars/v/com.github.liquidz/merr.svg["Clojars Project", link="https://clojars.org/com.github.liquidz/merr"] image:https://cljdoc.xyz/badge/com.github.liquidz/merr["cljdoc badge", link="https://cljdoc.xyz/d/com.github.liquidz/merr/CURRENT"]
Minimal and good enough error handling library for Clojure/ClojureScript (and also Babashka/nbb)
This library is based on https://adambard.com/blog/acceptable-error-handling-in-clojure/["Good Enough" error handling in Clojure].
== Concept
- Easy to imagine behavior
- Minimum to remember ** All usage and examples are documented in docstring
[source,clojure]
(require '[merr.core :as merr]) ;; => nil
;; for ClojureScript ;; (require '[merr.core :as merr :include-macros true])
(merr/let +err+ [foo 1 bar (merr/error) baz (* bar 2)] {:+err+ +err+ :foo foo :bar bar :baz baz}) ;; => {:+err+ (merr/error), :foo 1, :bar nil, :baz nil}
== Usage
=== error record
[source,clojure]
(defrecord MerrError [type message data cause])
=== let
[source,clojure]
(merr/let err [a 10 b (inc a) c (inc b)] (if err (merr/message err) (str "c = " c))) ;; => "c = 12"
(merr/let err [a 10 b (merr/error {:message "ERROR"}) c (inc b)] (if err (merr/message err) (str "c = " c))) ;; => "ERROR"
=== ->
[source,clojure]
(merr/-> 10 (+ 1) (- 1)) ;; => 10
(merr/-> 10 ((fn [_] (merr/error))) (- 1)) ;; => (merr/error)
=== ->>
[source,clojure]
(merr/->> 10 (+ 1) (- 1)) ;; => -10
(merr/->> 10 ((fn [_] (merr/error))) (- 1)) ;; => (merr/error)
=== try
[source,clojure]
(merr/try (throw (ex-info "ERROR" {}))) ;; => merr/error?
== Custom error
You can specify any keywords as :type, but you may want to define and use specific :type of errors in your project.
In that case, merr.helper is useful.
[source,clojure]
(require '[merr.helper :as merr.h]) ;; => nil
(def custom-error (partial merr.h/typed-error ::custom-error-type)) ;; => var?
(def custom-error? (partial merr.h/typed-error? ::custom-error-type)) ;; => var?
(custom-error? (custom-error {:message "custom error"})) ;; => true
typed-error? will check child error types, so you can define sub errors via clojure.core/derive.
[source,clojure]
(derive ::sub-custom-error-type ::custom-error-type) ;; => nil
(custom-error? (merr/error {:type ::sub-custom-error-type})) ;; => true
== Integration
=== clj-kondo
merr provies clj-kondo's configuration and hooks. To import configurations, run the following command.
[source,console]
clj-kondo --no-warnings --lint "$(clojure -Spath -Sdeps '{:deps {com.github.liquidz/merr {:mvn/version "LATEST"}}}')"
== Support
- Clojure
- ClojureScript
- https://github.com/babashka/babashka[Babashka]
- https://github.com/babashka/nbb[nbb]
== License
Copyright © 2018-2022 https://twitter.com/uochan[Masashi Iizuka]
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.