Skip to content

Instantly share code, notes, and snippets.

@cbilson
Created December 20, 2013 17:10
Show Gist options
  • Save cbilson/8058042 to your computer and use it in GitHub Desktop.
Save cbilson/8058042 to your computer and use it in GitHub Desktop.
(defmacro when-let->
"Takes an expression and a set of binding+test/form pairs. Threads expr (via ->)
through each form for which the corresponding test
expression is true, binding the result of the test."
[expr & clauses]
(assert (even? (count clauses)))
(let [g (gensym)
pstep (fn [[[res test] step]] `(if-let [~res ~test] (-> ~g ~step) ~g))]
`(let [~g ~expr
~@(interleave (repeat g) (map pstep (partition 2 clauses)))]
~g)))
(comment
;; Lame example: real world use is in a prismatic/schema schema I am trying to make
(let [[a b c] (repeatedly 3 (partial rand 10))
check (fn [n] (when (< 5 n) (str "ERROR: value to big:" n)))]
(when-let-> {}
[msg (check a)] (assoc :a (str msg ", regarding a"))
[msg (check b)] (assoc :b (str msg ", regarding b"))
[msg (check c)] (assoc :c (str msg ", regarding c"))))
RESULT: {:c "ERROR: value to big:6.131820288094671, regarding c"}
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment