I am learning about Clojure macros, and the code examples will sometimes have the constructs \'~symbol
or alternately ~\'symbol
. I know that (quo
~
is a reader macro for the unquote
function. within a quoted list it causes a symbol to be evaluated rather then used as a literal symbol
user> (def unquoted 4)
user>`(this is an ~unquoted list)
(user/this user/is user/an 4 clojure.core/list)
user>
everything except the symbol unquoted was used just as a symbol where unquoted was resolved to its value of 4. this is most often used in writing macros. The repl also prints the namespace (user) infront of the names when it is printing the resulting list.
many macros, are basically just templates designed to do a bunch of slight variations on something that can't be done in a function. In this contrived example a template macro defines a function by producing a call to def. syntax-quote with unquoting makes this much easier to read:
user> (defmacro def-map-reducer [name mapper reducer]
`(defn ~name [& args#]
(reduce ~reducer (map ~mapper args#))))
#'user/def-map-reducer
user> (def-map-reducer add-incs inc +)
#'user/add-incs
user> (add-incs 1 2 3 4 5)
20
compared to:
user> (defmacro def-map-reducer [name mapper reducer]
(let [args-name (gensym)]
(list `defn name [`& args-name]
(list `reduce reducer (list `map mapper args-name)))))
#'user/def-map-reducer
user> (def-map-reducer add-decs dec +)
#'user/add-decs
user> (add-decs 1 2 3 4 5)
10
user>
in the second example I also don't use the auto-gensyms feature because I'm not in a syntax-quote