传递给宏的变量在错误的命名空间中得到解析?

8

Noirdefpage让我有点麻烦。我正在尝试构建一个类似于这样的调用:

(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

看起来,noir 不是用这种方式使用的,因为它接受方法参数并将其转换为 compojure.core 中的符号(请参见 https://github.com/ibdknox/noir/blob/master/src/noir/core.clj#L36)。这意味着它不希望在此处使用变量,只允许使用字面值。所以我认为你无法对此做任何事情,除非向 noir 发布问题...


1

如果我们查看 noir/core.clj 文件(source),找到 parse-route 函数并推理它对其方法参数的操作(在那里称为 action),我们可以发现该方法关键字被转换为字符串,大写,并在 compojure.core 命名空间中解析。所有这些都是在宏展开期间完成的。因此,无法在不更改 noir 代码的情况下使用变量代替关键字。


1

我想这个问题和如何将Clojure的doc函数应用于一系列函数类似。宏可以对其参数进行任何操作,因此传递一个裸符号可能会导致不可预测的结果。

解决方案有一种方法,但不太优雅:

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

注意,my-method在此不是字面意思,因此它首先会在我们自己的命名空间中解析和评估,然后才进入eval。

0

将我的方法和它所在的命名空间一起传递怎么样:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接