cond->

added
1.5

ns
clojure.core

type
macro

(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"]