Search code examples
macrosclojurelispnoir

Variable passed to macro gets resolved in wrong namespace?


The Noir macro defpage is giving me a little bit of trouble. I am trying to construct a call similar to this:

(defpage [:post "some/url"] [data]
  ;; some stuff...
  )

However, instead of using the keyword :post I would like to use a variable, like this:

(def my-method :post)
(defpage [my-method "some/url"] [data]
  ;; some stuff...
  )

The problem is that when the macro expands, it wants to resolve the variable my-method in the compojure.core namespace instead of my own, giving me the error:

No such var: compojure.core/MY-METHOD

How can I force my-method to resolve in the current context?


Solution

  • I guess this is a similar problem to: How can I apply clojure's doc function to a sequence of functions A macro can do whatever it wants with its args, so passing a naked symbol in can result in unpredictable results.

    A way to solve it, but it ain't pretty:

    (eval (list 'defpage (vector my-method "some/url") '[data]
      ; some stuff
    ))
    

    Notice that my-method is not a literal here, so it gets resolved and evaluated in our own namespace first, before going into eval.