macro (clojure)

Table of Contents

1 Binding Variables in a Macro

this seems to work:

(defmacro with-listener [& form]
 `(let ~['listener (rand)] ~@form))

(with-listener (println listener) (* 2 listener))

let’s look at how the macro expands:

(macroexpand '(with-listener listener))
let* (listener 4) listener

where this does not work:

(defmacro with-listener-2 [& form]
 `(let [listener 4] ~@form))

(with-listener-2 (println listener) listener)
class clojure.lang.Compiler$CompilerException

why? Because listener must be passed in as a symbol, otherwise it is either evaluated now (in the macro) or evaluated in the macro expansion. This is because the let as a symbol itself expects another symbol to be passed in.

So, you could do something like this as opposed to the first version:

(defmacro with-listener-3 [& form]
 `(let [~'listener 4] ~@form))

(with-listener-3 (println listener) listener)

alternatively, you can pass in a binding symbol like this:

(defmacro with-listener-4 [bind-name & form]
 `(let [~bind-name ~(rand)] ~@form))

(with-listener-4 l
  (println l)
  (* 2 l))

Author: John Doe

Created: 2021-12-20 Mon 14:25