Clojure Programming/Examples/API Examples/Macros
->
[edit | edit source]This is the "threading" operator.
(macroexpand-1 '(-> true (if "clojure")))
=>(if true "clojure")
this:
user=> (-> "abc" .toUpperCase ,, (.replace ,, "B" "-"))
"A-C"
is equivalent to:
user=> (.replace (.toUpperCase "abc") "B" "-")
"A-C"
NOTE: you do not need to insert ',,', since clojure treats them like whitespace, but marking the forms second position this way enhances readability.
However -> works on everything
user=> (-> true (if ,, inc dec) (map ,, [1 2 3]))
(2 3 4)
or expanded
(map (if true inc dec) [1 2 3])
So one can also use macros and normal functions in ->, i.e. non-methods.
Here is an example that should make every devoted Programmer fall in love with lisp, if he compares it with equivalent Java code. Reading the name of the first entry in a zip file:
user=> (import '(java.net URL) '(java.util.zip ZipInputStream))
nil
user=> (-> "http://clojure.googlecode.com/files/clojure_20081217.zip" URL. .openStream ZipInputStream. .getNextEntry bean :name)
"clojure/"
cond
[edit | edit source]user=> (cond false 1 true 2)
2
user=> (cond nil 1 2 3)
3
condp
[edit | edit source](let [a 5]
(condp = a
1 "hi"
5 "fun"))
-> "fun"
The test expression (1 and 5 in the above example) is inserted as first parameter to the predicate function, the comparison expression (here a) as second. condp throws an java.lang.IllegalArgumentException if no clauses are matched in the above example. condp also allows to add a single default expression after the clauses whose value will be returned if no clauses matches.
(let [a 7]
(condp = a
1 "hi"
5 "fun"
"no match"))
-> "no match"