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.
;; 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])
Threads the expr through the forms. Inserts x as the last item in the first form, making a list of...
Binds name to expr, evaluates the first form in the lexical context of that binding, then binds na...
Returns the value in a nested associative structure, where ks is a sequence of keys. Returns nil i...
When expr is not nil, threads it into the first form (via ->), and when that result is not nil, th...
Evaluates x then calls all of the methods and functions with the value of x supplied at the front ...
form => fieldName-symbol or (instanceMethodName-symbol args*) Expands into a member access (.) of...
See also ->> which is similar but threads the first expr as the last argument of the forms.
I have a short blog on this, in case you are still confused on it and understand Chinese.