Are the ->
and ->>
macros only to make the code more readable or they have also other specific functions?
1 Answers
The thread-first (->
) and thread-last (->>
) are there to make code more readable. But that's already pretty important !
It allows to un-nest function calls (example taken from clojuredocs) :
;; Arguably a bit cumbersome to read:
user=> (first (.split (.replace (.toUpperCase "a b c d") "A" "X") " "))
"X"
;; Perhaps easier to read:
user=> (-> "a b c d"
.toUpperCase
(.replace "A" "X")
(.split " ")
first)
It also allows you to put the emphasis on something. For instance, consider :
(-> {... }
...
...
(count))
(count (...(... {...})))
In the first example, it is very clear that you start with a map, and then do something to it. In the second, it is clear that you count something.
The preference depends on what you want to put forward.
Also, the choice of ->
vs ->>
is a clear visual indicator : are you operating or not on collections ? This is made immediately obvious (this is a convention in Clojure to have the collection as a last parameter).
So yes, it is "only" readability, but that is a very important part of building programs, and Clojure gives you tools to make your code read naturally. When choosing one solution, I try to consider the way Clojure will be read.
-
2It's also worth noting that there's a family of related conditional threading macros which *do* add additional functionality on top of that. `some->` and `some->>` thread first and last as above, but halt evaluation if any step returns `nil`, a la the maybe monad. `cond->` and `cond->>` test a conditional to decide whether or not to pass the value through each of the threaded forms. – Magos Aug 23 '15 at 13:52
-
1@nha Thank you, it is very clear now! By the way a new question came up to me reading your nice answer: do the points before the method names indicate java methods? (in `.replace` `.toUpperCase`) and is there any difference or benefit between calling the java methods vs. clojure libraries: `(clojure.string/replace)` `(clojure.string/upper-case)` ? – Aug 23 '15 at 21:15
-
@AmirTeymuri glad you like it :) Yes, those are Java methods (I just took the example from clojuredocs but yes the Clojure methods are more idiomatic). Also, when calling Java methods that are not in a Clojure namespace, you may be interested in the `doto` macro. – nha Aug 23 '15 at 22:34
-
Why oh why name it 'threading' when it is really more like 'pipe'? – Frank C. Aug 24 '15 at 17:25