Minimal Railway Oriented Programming for Clojure.
->result is the only macro)clojure.core only)[org.clojars.konkon/railway-clj "0.2.0"]
Results are expressed as tagged tuples:
[:ok value] ;; success
[:err reason] ;; failure
Plain data, so assoc, merge, print, read all work as expected.
(require '[railway-clj.core :as r])
(r/ok 42) ;; => [:ok 42]
(r/err "not found") ;; => [:err "not found"]
(r/ok? (r/ok 42)) ;; => true
(r/err? (r/err "x")) ;; => true
(r/unwrap (r/ok 42)) ;; => 42
(r/unwrap (r/err "reason")) ;; => "reason"
(r/then (r/ok 5) inc)
;; => [:ok 6]
(r/then (r/err "fail") inc)
;; => [:err "fail"] (passes through unchanged)
;; When f returns a result, it is used as-is
(r/then (r/ok 10) #(if (> % 5) (r/err "too big") (r/ok %)))
;; => [:err "too big"]
(r/recover (r/err "fail") (fn [_] (r/ok "default")))
;; => [:ok "default"]
(r/recover (r/ok 42) (fn [_] (r/ok "default")))
;; => [:ok 42] (passes through unchanged)
(r/branch (r/ok 42)
#(str "value: " %)
#(str "error: " %))
;; => "value: 42"
(r/or-else (r/err "fail") (r/ok 0))
;; => [:ok 0]
(r/or-else (r/ok 42) (r/ok 0))
;; => [:ok 42]
(def process (r/pipeline inc #(* % 2)))
(process 5) ;; => [:ok 12]
(process 2) ;; => [:ok 6]
;; Short-circuits on failure
(def safe-process
(r/pipeline
inc
#(if (> % 5) (r/err "too big") %)
#(* % 2)))
(safe-process 2) ;; => [:ok 6]
(safe-process 5) ;; => [:err "too big"]
(-> (r/ok 5)
(r/then inc)
(r/then #(* % 2)))
;; => [:ok 12]
(r/->result (/ 10 5))
;; => [:ok 2]
(r/->result (/ 10 0))
;; => [:err {:type :exception, :message "Divide by zero"}]
All operation functions have symbolic aliases. They are identical functions bound via def.
| Name | Symbol | Meaning |
|---|---|---|
then | >> | Flow success value forward |
recover | << | Recover from failure |
branch | >< | Branch on success/failure |
or-else | \|? | Return alternative on failure |
pipeline | >>> | Compose functions sequentially |
(require '[railway-clj.core :as r])
;; Readable names
(-> (r/ok 5)
(r/then inc)
(r/then #(* % 2)))
;; => [:ok 12]
;; Symbolic (same result)
(-> (r/ok 5)
(r/>> inc)
(r/>> #(* % 2)))
;; => [:ok 12]
lein test
MIT License
Can you improve this documentation? These fine people already did:
Takayuki-Y5991 & konkonEdit on GitHub
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 |