Переменная, переданная макросу, разрешается в неправильном пространстве имен? - PullRequest
8 голосов
/ 04 декабря 2011

Макрос Нуар defpage доставляет мне немного хлопот.Я пытаюсь создать вызов, подобный следующему:

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

Однако вместо использования ключевого слова :post я хотел бы использовать переменную, например:

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

Проблема в том, что когда макрос расширяется, он хочет разрешить переменную my-method в пространстве имен compojure.core вместо моего собственного, что дает мне ошибку:

No such var: compojure.core/MY-METHOD

Как я могу форсировать my-methodразрешить в текущем контексте?

Ответы [ 4 ]

1 голос
/ 04 декабря 2011

Если мы посмотрим файл noir / core.clj ( source ), найдем функцию parse-route и объясним, что она делает с аргументом метода (там это называется действием), мы могли бы найти этот метод Ключевое слово преобразуется в строку, в верхнем регистре и разрешается в пространстве имен compojure.core. Все это делается во время расширения макроса. Поэтому невозможно использовать переменную вместо ключевого слова без изменения нуар-кода.

1 голос
/ 04 декабря 2011

Кажется, что noir не предназначен для использования таким образом, потому что он принимает аргумент метода и преобразует его в символ в compojure.core (см. https://github.com/ibdknox/noir/blob/master/src/noir/core.clj#L36). Это означает, что он не ожидает переменная в этом месте, только литералы. Так что я не думаю, что вы можете что-то с этим поделать, кроме как отправить сообщение в noir ...

1 голос
/ 04 декабря 2011

Я полагаю, что эта проблема похожа на: Как применить doc-функцию clojure к последовательности функций Макрос может делать с аргументами все, что хочет, поэтому передача пустого символа может привести к непредсказуемым результатам.

Способ решить это, но это не красиво:

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

Обратите внимание, что my-method здесь не является литералом, поэтому он сначала разрешается и оценивается в нашем собственном пространстве имен, прежде чем перейти к eval.

0 голосов
/ 04 декабря 2011

Как насчет передачи my-метода вместе с пространством имен, в котором он находится:

(defpage [myns/my-method "some/url"] [data]
;;
)
...