store/[org.clojure/clojure "1.8.0"] clj::clojure.core/cond->

Community Documentation



[expr & clauses] -> Val


Takes an expression expr and a series of test, form pairs. Threads the expr through each form as if by clj::clojure.core/-> when the corresponding test is truthy. Unlike clj::clojure.core/cond, does not short circuit on the first true test expression, so all tests will be evaluated and all forms may be applied to expr.


Composes nicely with clj::clojure.core/-> and clj::clojure.core/->> to express several applications on a single expr. Also composes with clj::clojure.core/as-> and itself.

While cond-> can succinctly express huge chains of sequential conditional updates, taste should be used to avoid repetition, limit length and ensure reusability.


(defmacro cond->
  "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."
  {:added "1.5"}
  [expr & clauses]
  (assert (even? (count clauses)))
  (let [g (gensym)
        steps (map (fn [[test step]] `(if ~test (-> ~g ~step) ~g))
                   (partition 2 clauses))]
    `(let [~g ~expr
           ~@(interleave (repeat g) (butlast steps))]
       ~(if (empty? steps)
          (last steps)))))

Example 1

(defn foo
  "Function from a number X to an even number X'. If X is even,
  returns (* 2 (+ x 1)), otherwise (* x 2)."
  (cond-> x
    (even? x) ;; If x is even, add 1 to make it odd

    :true     ;; Double every x with a truthy constant
    (* 2)))
;; => #'user/foo

(foo 3)
;; => 6

(foo 4)
;; => 10

Uses on crossclj