clojure Macros Syntax quoting and unquoting


Example

Example from the standard library (core.clj:807):

(defmacro and
  "Evaluates exprs one at a time, from left to right. If a form
  returns logical false (nil or false), and returns that value and
  doesn't evaluate any of the other expressions, otherwise it returns
  the value of the last expr. (and) returns true."
  {:added "1.0"}
  ([] true)
  ([x] x)
  ([x & next]
   `(let [and# ~x]
      (if and# (and ~@next) and#))))
  • ` called syntax-quote is like (quote), but recursive: it causes (let …), (if …), etc to not evaluate during macro expansion but to output as is
  • ~ aka unquote cancels syntax-quote for single form inside syntax-quoted form. So x's value is outputted when expanding macro (instead of outputting x symbol)
  • ~@ aka unquote-splicing is like unquote but takes list argument and expands it, each list item to separate form
  • # appends unique id to symbols to prevent name conflicts. It appends the same id for the same symbol inside syntax-quoted expression, so and# inside let and and# inside if will get the same name