ClojureDocs

Nav

Namespaces

->

clojure.core

Available since 1.0 (source)
  • (-> x & forms)
Threads the expr through the forms. Inserts x as the
second item in the first form, making a list of it if it is not a
list already. If there are more forms, inserts the first form as the
second item in second form, etc.
9 Examples
;; Use of `->` (the "thread-first" macro) can help make code
;; more readable by removing nesting. It can be especially
;; useful when using host methods:

;; 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)
"X"

;; It can also be useful for pulling values out of deeply-nested
;; data structures:
user=> (def person 
            {:name "Mark Volkmann"
             :address {:street "644 Glen Summit"
                       :city "St. Charles"
                       :state "Missouri"
                       :zip 63304}
             :employer {:name "Object Computing, Inc."
                        :address {:street "12140 Woodcrest Dr."
                                  :city "Creve Coeur"
                                  :state "Missouri"
                                  :zip 63141}}})
 
user=> (-> person :employer :address :city)
"Creve Coeur"

;; same as above, but with more nesting
user=> (:city (:address (:employer person)))
"Creve Coeur"

;; Note that this operator (along with ->>) has at times been
;; referred to as a 'thrush' operator.

;; http://blog.fogus.me/2010/09/28/thrush-in-clojure-redux/
;; Your own REPL! (Read Eval Print Loop)

;; We would need a little helper macro for that
;; It does what its name says - loops forever
user=> (defmacro loop-forever [& body] `(loop [] ~@body (recur)))

;; Your own REPL
user=> (loop-forever (println (eval (read))))                                                                     
(+ 1 2)
3

;; If you read the above code left to right (outside in) it reads LPER.
;; Inside out it reads REPL alright.

;; Sometimes it might be easier to read code outside in, just like a sequence of steps:
;; 1. Read, 2. Eval, 3. Print, 4. Loop
;; Here's how -> helps you:

user=> (-> (read) (eval) (println) (loop-forever))                                                                
(+ 1 2)
3

;; Does that read easier for you? If it does, -> is your friend!

;; To see what Clojure did behind the scenes with your -> expression:
user=> (require 'clojure.walk)
nil
user=> (clojure.walk/macroexpand-all '(-> (read) (eval) (println) (loop-forever)))
(loop* [] (println (eval (read))) (recur))

;; You can even use ->'s cousin ->> to setup your own REPL:
user=> (->> (read) (eval) (println) (while true))
(+ 1 2)
3

;; Can you see why we can't use -> to write the above?

user=> (def c 5)
user=> (-> c (+ 3) (/ 2) (- 1))                          
3

;; and if you are curious why
user=> (use 'clojure.walk)
user=> (macroexpand-all '(-> c (+ 3) (/ 2) (- 1)))
(- (/ (+ c 3) 2) 1)
;; simplest usage example, fill as second item in the first and second form

user=> (-> "foo"
           (str "bar")
           (str "zoo"))
"foobarzoo"
user=> (str "foo" "bar")
"foobar"
user=> (str (str "foo" "bar") "zoo")
"foobarzoo"
(-> 3 (- 2)) ; It means (- 3 2)
=> 1

(->> 3 (- 2)) ; It means (- 2 3)
=> -1

(doto 3 (- 2)) ; It means (- 3 2) but return the first object 3
=> 3
;; Be cautious with anonymous functions; they must be wrapped in an outer
;; pair of parens.
(-> 10
    #(/ % 2))
;; will throw an exception, but
(-> 10
    (#(/ % 2)))
;; will work fine. Similarly,
(-> 10
    (fn [n] (/ n 2)))
;; will throw an exception, but
(-> 10
    ((fn [n] (/ n 2))))
;; works as intended.
;; How to thread functions that expect more than one argument

;; Say you want to thread this.
user=> (inc (/ 10 2))
=> 6

;; This obviously won't work
user=> (-> 2 10 / inc)
=> ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn

;; Since Clojure is expecting a function instead of `10` in `(10 2)`
user=> (clojure.walk/macroexpand-all '(-> 2 10 + inc))
=> (inc (+ (10 2)))

;; Instead you have two options, either just
user=> (-> (/ 10 2) inc)
=> 6

;; or
user=> (-> 10 (/ 2) inc)
=> 6
;; For large threads you can use commas (interpreted as whitespaces) 
;; to visualize where the items are going to be inserted.

user=> (-> + (reduce 10 [6 4]) (* 5) (/ 100))
=> 1

;; with two commas (you can use one if you prefer)
user=> (-> + (reduce ,, 10 [6 4]) (* ,, 5) (/ ,, 100))
=> 1

;; For instance:
;; (reduce ,, 10 [6 4])
;; means
;; (reduce + 10 [6 4])
;; 4Clojure Question 38

(= (#(-> %& 
       sort 
       reverse 
       first)  1 8 3 4) 8)
See Also

Threads the expr through the forms. Inserts x as the last item in the first form, making a list of...

Added by boxie

Binds name to expr, evaluates the first form in the lexical context of that binding, then binds na...

Added by phreed

Returns the value in a nested associative structure, where ks is a sequence of keys. Returns nil i...

Added by phreed

When expr is not nil, threads it into the first form (via ->), and when that result is not nil, th...

Added by pladdy

Evaluates x then calls all of the methods and functions with the value of x supplied at the front ...

Added by jw-00000

form => fieldName-symbol or (instanceMethodName-symbol args*) Expands into a member access (.) of...

Added by mars0i
3 Notes
    By , created 14.7 years ago

    See also ->> which is similar but threads the first expr as the last argument of the forms.

    By , created 11.7 years ago, updated 11.7 years ago

    I have a short blog on this, in case you are still confused on it and understand Chinese.

    By , created 10.5 years ago

    Can be used as an alternative to get-in.