What is the difference between the ->
and ->>
macros in Clojure?
It's a way to write code left to right, instead of inside out, e.g. (reduce (map (map xs bar) foo) baz) becomes (-> xs (map bar) (map foo) (reduce baz))
It has no syntactic meaning. It is just part of the symbol name. In Lisps, the arrow -> (or even just '>') is often used to imply conversion of, or casting of, one type into another.
Clojure has a programmatic macro system which allows the compiler to be extended by user code. Macros can be used to define syntactic constructs which would require primitives or built-in support in other languages. Many core constructs of Clojure are not, in fact, primitives, but are normal macros.
The docs A. Webb linked to explain the "what", but don't do a good job of the "why".
As a rule, when a function works on a singular subject, that subject is the first argument (e.g., conj
, assoc
). When a function works on a sequence subject, that subject is the last argument (e.g., map
, filter
).
So, ->
and ->>
are documented as threading the first and last arguments respectively, but it is also useful to think of them as applying to singular or sequential arguments respectively.
For example, we can consider a vector as a singular object:
(-> [1 2 3] (conj 4) ; (conj [1 2 3] 4) (conj 5) ; (conj [1 2 3 4] 5) (assoc 0 0)) ; (assoc [1 2 3 4 5] 0 0) => [0 2 3 4 5]
Or we can consider it as a sequence:
(->> [1 2 3] (map inc) ; (map inc [1 2 3]) (map inc) ; (map inc (2 3 4)) (concat [0 2])) ; (concat [0 2] (3 4 5)) => (0 2 3 4 5)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With