Open main menu

Wikibooks β

Clojure Programming/Examples/API Examples/Macros

< Clojure Programming‎ | Examples‎ | API Examples


This is the "threading" operator.

(macroexpand-1 '(-> true (if "clojure")))
=>(if true "clojure")


user=> (-> "abc" .toUpperCase ,, (.replace ,, "B" "-"))

is equivalent to:

user=> (.replace (.toUpperCase "abc") "B" "-")

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 '( URL) '( ZipInputStream))
user=> (-> "" URL. .openStream ZipInputStream. .getNextEntry bean :name)


user=> (cond false 1 true 2)
user=> (cond nil 1 2 3)


(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"