I've run in several situations where I want to do a chain of operations on an object with optional functions. "->" works great for sequences of commands on the same object (ex. (c (b (a x))) becomes (-> x a b c) ), except if some operations are optional. For example, suppose I wanted to do:
(c
(if (> (a x) 2)
(b (a x))
(a x)
)
)
Is there any way to do that in a clearer fashion using an operation like "->"?
You can do it with cond->
, newly introduced in Clojure 1.5:
(cond-> x
true a
(> (a x) 2) b
true c)
Or, better,
(-> x
a
(cond-> (> (a x) 2) b)
c)
Meaning, "take x
, thread it through a
, take the result and thread it through b
if (> (a x) 2)
or else leave it unchanged, finally take what you've got and thread it through c
".
In other words, cond->
is like ->
, except instead of single forms to thread your expression through it takes test+form pairs, where the form is skipped if test is falsey and used for threading if test is truthy:
(cond-> x
test-1 form-1
test-2 form-2)
;; if test-1 is truthy and test-2 is falsey, output is as if from
(-> x test-1)
;; if it's the other way around, output is as if from
(-> x test-2)
;; if both tests are truthy:
(-> x test-1 test-2)
;; if both tests are falsey:
x
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With