4

Are the -> and ->> macros only to make the code more readable or they have also other specific functions?

1 Answers1

7

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.

Community
  • 1
  • 1
nha
  • 17,623
  • 13
  • 87
  • 133
  • 2
    It'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