Skip to content

Instantly share code, notes, and snippets.

@richhickey
Created October 13, 2012 17:43
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save richhickey/3885504 to your computer and use it in GitHub Desktop.
Save richhickey/3885504 to your computer and use it in GitHub Desktop.
new thread macros draft
(defmacro test->
"Takes an expression and a set of test/form pairs. Threads expr (via ->)
through each form for which the corresponding test expression (not threaded) is true."
[expr
& clauses]
(assert (even? (count clauses)))
(let [g (gensym)
pstep (fn [[test step]] `(if ~test (-> ~g ~step) ~g))]
`(let [~g ~expr
~@(interleave (repeat g) (map pstep (partition 2 clauses)))]
~g)))
(defmacro test->>
"Takes an expression and a set of test/form pairs. Threads expr (via ->>)
through each form for which the corresponding test expression (not threaded) is true."
[expr & clauses]
(assert (even? (count clauses)))
(let [g (gensym)
pstep (fn [[test step]] `(if ~test (->> ~g ~step) ~g))]
`(let [~g ~expr
~@(interleave (repeat g) (map pstep (partition 2 clauses)))]
~g)))
(defmacro let->
"Binds name to expr, evaluates the first form in the lexical context
of that binding, then binds name to that result, repeating for each
successive form"
[expr name & forms]
`(let [~name ~expr
~@(interleave (repeat name) forms)]
~name))
(defmacro when->
"When expr is logical true, threads it into the first form (via ->),
and when that result is logical true, through the next etc"
[expr & forms]
(let [g (gensym)
pstep (fn [step] `(when ~g (-> ~g ~step)))]
`(let [~g ~expr
~@(interleave (repeat g) (map pstep forms))]
~g)))
(defmacro when->>
"When expr is logical true, threads it into the first form (via ->>),
and when that result is logical true, through the next etc"
[expr & forms]
(let [g (gensym)
pstep (fn [step] `(when ~g (->> ~g ~step)))]
`(let [~g ~expr
~@(interleave (repeat g) (map pstep forms))]
~g)))
;; examples
(test-> []
(< 2 3) (conj :a)
42 (conj :b)
(> 2 3) (conj :nope)
:go (conj :more))
;; [:a :b :more]
(let-> [] x
(conj x :a)
(if :nested
(conj x :b)
(conj x :d))
(conj x :c))
;; [:a :b :c]
(when-> {:a {:b {:c 42}}}
:a :b :c)
;; 42
(when-> {:a {:b {:c 42}}}
:a :d .blowup)
;; nil
@ptaoussanis
Copy link

These are great - situations come up all the time where this'd be useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment