Variable passed to macro gets resolved in wrong namespace?
Asked Answered
A

4

8

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?

Aleishaalejandra answered 3/12, 2011 at 23:21 Comment(0)
S
1

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.

Snowy answered 4/12, 2011 at 8:54 Comment(0)
E
1

It seems, that noir is not meant to be used this way, because it takes the method argument and transforms it to the symbol in compojure.core (see https://github.com/ibdknox/noir/blob/master/src/noir/core.clj#L36). It means, that it doesn't expect a variable in this place, only literals. So I don't think you can do anything about that, except post an issue to noir...

Excellency answered 4/12, 2011 at 8:52 Comment(0)
S
1

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.

Snowy answered 4/12, 2011 at 8:54 Comment(0)
S
1

If we look through noir/core.clj file (source), find parse-route function and reason what it does with its method argument (it is called action there), we could find that method keyword is converted to string, uppercased and resolved in compojure.core namespace. All this is done during macro expansion time. So it is not possible to use variable instead of keyword without altering noir code.

Saida answered 4/12, 2011 at 9:2 Comment(0)
A
0

What about passing my-method along with namespace it is in:

(defpage [myns/my-method "some/url"] [data]
;;
)
Aerometer answered 4/12, 2011 at 8:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.