(cond-> expr & clauses)
Takes an expression and a set of test/form pairs. Threads expr (via ->) through each form for which the corresponding test expression is true. Note that, unlike cond branching, cond-> threading does not short circuit after the first true test expression.
(cond-> 1 ; we start with 1
true inc ; the condition is true so (inc 1) => 2
false (* 42) ; the condition is false so the operation is skipped
(= 2 2) (* 3)) ; (= 2 2) is true so (* 2 3) => 6
;;=> 6
;; notice that the threaded value gets used in
;; only the form and not the test part of the clause.
;; Useful when you want to conditionally evaluate expressions and thread them
;; together. For instance, the following returns a vector containing the names
;; (as symbols) of the implementing classes of obj.
=> (defn instance->types
[obj]
(cond-> []
(instance? java.util.SortedMap obj) (conj 'SortedMap)
(instance? java.util.AbstractMap obj) (conj 'AbstractMap)))
#'user/instance->types
=> (def hm (java.util.HashMap.))
#'user/hm
=> (instance->types hm)
[AbstractMap]
=> (def tm (java.util.TreeMap.))
#'user/tm
=> (instance->types tm)
[SortedMap AbstractMap]
=> (defn divisible-by? [divisor number]
(zero? (mod number divisor)))
#'user/divisible-by?
=> (defn say [n]
(cond-> nil
(divisible-by? 3 n) (str "Fizz")
(divisible-by? 5 n) (str "Buzz")
:always (or (str n))))
#'user/say
=> (say 1)
"1"
=> (say 3)
"Fizz"
=> (say 5)
"Buzz"
=> (say 15)
"FizzBuzz"
(let [x 1 y 2]
(cond-> []
(odd? x) (conj "x is odd")
(zero? (rem y 3)) (conj "y is divisible by 3")
(even? y) (conj "y is even")))
;=> ["x is odd" "y is even"]
;;; IS Equivalent to
(let [x 1 y 2]
(as-> [] <>
(if (odd? x)
(conj <> "x is odd")
<>)
(if (zero? (rem y 3))
(conj <> "y is divisible by 3")
<>)
(if (even? y)
(conj <> "y is even")
<>)))
;=> ["x is odd" "y is even"]