macro | since v0.0-927 | imported clojure.core/-> | Edit |
(-> x & forms)
The thread-first macro "threads" an expression through several forms as the second item in a list.
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.
Code | Expands To |
---|---|
(-> x (a b c) d (x y z)) |
(x (d (a x b c)) y z) |
The first is arguably a bit more cumbersome to read than the second:
(first (.split (.replace (.toUpperCase "a b c d") "A" "X") " "))
;;=> "X"
(-> "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:
(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}}})
(-> person :employer :address :city)
;;=> "Creve Coeur"
Same as above, but with more nesting:
(:city (:address (:employer person)))
;;=> "Creve Coeur"
It can also help with arithmetic:
(def c 5)
(-> c (+ 3) (/ 2) (- 1))
;;=> 3
Same as above, but with more nesting:
(- (/ (+ c 3) 2) 1)
;;=> 3
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.
(defmacro ->
{:added "1.0"}
[x & forms]
(loop [x x, forms forms]
(if forms
(let [form (first forms)
threaded (if (seq? form)
(with-meta `(~(first form) ~x ~@(next form)) (meta form))
(list form x))]
(recur threaded (next forms)))
x)))