Difference between arrow and double arrow macros in Clojure

Solution 1:

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)