A transformation pipeline passes an initial value through successive operations, letting each result become the next operation’s input. Clojure’s threading macros make these steps read in execution order instead of nested, inside-out order. section 2.3.2 section 2.3.1
Choose the threading macro according to where the current value belongs:
- Use -> when the value should become the first argument of each form. section 2.3.1
- Use ->> when the value should become the last argument, especially for sequence-processing operations. section 2.3.2
- Both macros accept an expression followed by optional forms, evaluate each step in order, and return the final result; with no forms, they return the expression. section 2.3.2 section 2.3.1
- Each form must begin with a callable; missing arguments cause ArityException, while non-callable forms cause ClassCastException. section 2.3.2 section 2.3.1
Threading an HTTP request transformation
A request can be prepared by adding a URL and coordinate vector, removing temporary fields, and updating its trace: (defn prepare [req] (-> req (assoc :url (str (:host req) (:path req)) :coord [(Double/valueOf (:x req)) (Double/valueOf (:y req))]) (dissoc :x-forward-to :x :y) (update :trace conj :prepared))). The result retains the useful request data and records :prepared. section 2.3.1
Threading sequence filters
(->> (range 1000) (filter even?) (filter #(zero? (mod % 3))) (filter #(apply = (str %))) (filter pos?)) returns (6 66 222 444 666 888). The last-position convention matches sequence functions naturally. section 2.3.2
(defn prepare [req] ; #1
(-> req
(assoc :url (str (:host req) (:path req))
:coord [(Double/valueOf (:x req)) (Double/valueOf (:y req))])
(dissoc :x-forward-to :x :y)
(update :trace conj :prepared)))
Inspect the complete -> request-preparation pipeline and compare its linear form with the nested alternative. section 2.3.1
(defn params [query] ; #1
(->> (split query #"&")
(map #(split % #"="))
(map #(apply hash-map %))
(apply merge)))
Inspect a complete ->> query-string parser that splits, maps, converts, and merges successive results. section 2.3.2
