cond-> conditionally threads an expression into the first argument position of successive forms. Each clause-form pair decides whether that transformation is applied, making optional updates readable as a top-to-bottom pipeline. section 2.3.3
Use the following contract to predict its behavior:
- Start with a mandatory expression, then provide zero or more clause-form pairs. section 2.3.3
- Evaluate each clause in the surrounding lexical context; clauses cannot refer to the result produced by an earlier form. section 2.3.3
- Thread the current value into a selected form's first argument position, wrapping non-list forms as needed. section 2.3.3
- Skip only the form whose clause is false; continue evaluating later pairs rather than short-circuiting. section 2.3.3
- Return the last transformed value, or the original expression when no form runs. section 2.3.3
Conditionally transform a value
These two expressions are equivalent: (let [x "123"] (if (string? x) (Integer. x) x)) (let [x "123"] (cond-> x (string? x) Integer.)) Both produce the integer 123. For several optional updates, keep the transformations in sequence: (cond-> m :always (assoc-in [:k3 :j1] "default") (same-initial? m) (assoc :same true) (map? (:k2 m)) (assoc :k2 (apply str (vals (:k2 m))))) The predicates inspect the original local binding m, while the selected forms transform the current threaded value. section 2.3.3
Listing 2.17. → functional composition, threading macro, conditional functional application
(cond-> [expr & clauses]) (cond->> [expr & clauses])
The compact syntax reference shows cond-> and its thread-last counterpart cond->> as conditional threading macros. section 2.3.3
