ClojureDocs

Nav

Namespaces

cond->

clojure.core

Available since 1.5 (source)
  • (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.
7 Examples

(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"] 
; Consider a code snippet that coerces any string to an integer, else noop:
(let [x "123"] 
  (if (string? x) 
    (Integer. x) 
    x))

; We can reduce the repetition of `x` by using `cond->`
(let [x "123"] 
  (cond-> x 
    (string? x) (Integer.))) 
;; always returns 1
(defn f [x] 1)

;; cond-> doesn't short circuit on nil
(cond-> nil
  true  f
  false inc
  true  inc)
;=> 2
;; If most of a -> is unconditional but one step is conditional, cond-> is useful:

(-> {}
    (assoc :foo "foo")
    (cond-> false
      (assoc :truthy true))
    (assoc :bar "bar"))
;; => {:foo "foo", :bar "bar"}


(-> {}
    (assoc :foo "foo")
    (cond-> true              ; this is the only change from above
      (assoc :truthy true))
    (assoc :bar "bar"))
;; => {:foo "foo", :truthy true, :bar "bar"}
See Also

Takes an expression and a set of test/form pairs. Threads expr (via ->>) through each form for whi...

Added by abrooks

Threads the expr through the forms. Inserts x as the second item in the first form, making a list ...

Added by abrooks

Threads the expr through the forms. Inserts x as the last item in the first form, making a list of...

Added by abrooks

Binds name to expr, evaluates the first form in the lexical context of that binding, then binds na...

Added by abrooks

When expr is not nil, threads it into the first form (via ->), and when that result is not nil, th...

Added by abrooks

When expr is not nil, threads it into the first form (via ->>), and when that result is not nil, t...

Added by abrooks

Takes a set of test/expr pairs. It evaluates each test one at a time. If a test returns logical t...

Added by abrooks

Evaluates test.

Added by MicahElliott
0 Notes
No notes for cond->