Search code examples
clojuremacros

Clojure macro: getting syntax-quoted/namespace-qualified symbol


Let’s say that I want to define a macro called defsomething such that this:

(defspecial a x)

…expands into this:

(def a (f `a x))

That syntax-quotation `a there is the tricky part. I don’t see how I can attach the current namespace to the symbol properly so that it behaves like the syntax-quote. For instance:

(defmacro defspecial [var-symbol expr]
  `(def ~var-symbol (f '~var-symbol ~expr)))

(defspecial a x)

…expands into:

(def a (f 'a x))

…which is close, but that second a is not namespace-qualified.

I know I could use *ns*:

(defmacro defspecial [var-symbol expr]
  `(def ~var-symbol (f (symbol (name (ns-name *ns*)) (name '~var-symbol)) ~expr)))

…but I don’t like that; not only is it ugly, *ns* is rebindable, so this would be possible:

(binding [*ns* (the-ns 'clojure.core)]
  (defspecial a 5))

Unfortunately, Clojure apparently has no syntax-quote form for ` like it has quote for '. And so, how should I best implement this macro, then?


Solution

  • Have you actually tried the last example you gave? The compiler's binding of *ns* happens at compile-time, as does the macroexpansion, so the run-time binding you do should have no effect on the behavior of defspecial.