Clojure - Writing Macros

1 minute read

Writring Macros

Macro structure

Macros are structured the same way as functions, they have a docstring, arguments and body. We can also use argument destructuring and can create multiple arity macros.

1(defmacro infix
2  "Use infix syntax for calling functions"
3  [[operand1 op operand2]]
4  (list op operand1 operand2))

Building Macros

Distinguishing Symbols and Values

Macro body always tries to get the value of the symbol. We sometimes want to return the symbol itself without getting its value. To turn off this evaluation Clojure uses a single quote character '.

 1(defmacro my-print-error
 2  "Prints and returns a result of expression but errors"
 3  [expression]
 4  (list let [result expression]
 5        (list println result)
 6        (result)))
 7
 8(defmacro my-print
 9  [expression]
10  (list 'let ['result expression]
11        (list 'println 'result)
12        ('result)))

In this example we use quoting to stop Clojure from evaluating let and println. We also use it to bind result so we can get its value.

Syntax Quoting

Syntax quoting is similar to regular quoting in that it returns unevaluated data structures, but they differ in that syntax quoting will return fully qualified symbols (symbols with the symbol’s namespace included).

1'+
2; => +
3
4`
5; => clojure.core/+

Another difference is that syntax quoting allows us to unqoute forms using tilde ~.

1`(+ 1 ~(inc 1))
2; => (clojure.core/+ 1 2)
3
4`(+ 1 (inc 1))
5; => (clojure.core/+ 1 (clojure.core/inc 1))

Syntax quoting leads to more readable and concise code.