Threading Macros

;; -> thread-first: inserts each result as the FIRST argument of the next form
(-> {:name "Ana" :age 30}
    (assoc :email "[email protected]")
    (update :age inc)
    (dissoc :name))                  ; {:age 31, :email "[email protected]"}

;; ->> thread-last: inserts as the LAST argument (good for sequence functions)
(->> (range 10)
     (filter even?)
     (map #(* % %))
     (reduce +))                     ; 120

;; as-> : name the threaded value for arbitrary positions
(as-> [1 2 3] $
  (map inc $)
  (reduce + $)
  (str "Total: " $))                 ; "Total: 9"

;; some-> / some->> : stop at the first nil
(some-> {:user {:address nil}} :user :address :city clojure.string/upper-case)   ; nil, no NPE

;; cond-> / cond->> : conditionally apply steps
(defn build-query [{:keys [limit sort]}]
  (cond-> {:select :*}
    limit (assoc :limit limit)
    sort  (assoc :order-by sort)))
(build-query {:limit 10})            ; {:select :*, :limit 10}

;; doto: call methods on a Java object, return the object
(doto (java.util.ArrayList.) (.add 1) (.add 2))   ; [1 2]