我有一个宏生成宏,我试图从另一个命名空间调用它,但它失败并显示“无法引用不存在的合格变量”。
我设法在下面的代码中重现它,这是最简单的例子,可以说明问题。我还找到了一种解决方法,但是我想了解问题的原因以及是否存在更好的解决方案。
问题
文件 foo.clj
(ns foo)
(defmacro create-my-macro []
`(defmacro my-macro []
nil))
文件 boo.clj
(ns boo (:use [foo]))
(create-my-macro)
上面的代码执行时:
java -cp clojure-1.4.0.jar clojure.main boo.clj
...失败:
Exception in thread "main" java.lang.RuntimeException: Can't refer to qualified var that doesn't exist, compiling:(...boo.clj:2)
解决方法
出于某种原因,当宏生成宏被增强以接受要创建的宏的名称作为参数时,没有失败。
文件 foo.clj
(ns foo)
(defmacro create-my-macro [macroName]
(let [the-macroName (symbol macroName)]
`(defmacro ~the-macroName []
1)))
文件 boo.clj
(ns boo (:use [foo]))
(create-my-macro "foo")
(println (foo))
如上所述运行文件 boo.clj 在控制台上输出一个干净的“1”,没有任何抱怨。
那么,在第一种情况下出了什么问题,是否有另一种方法可以修复它,更改宏生成宏以接受要生成的宏的名称作为参数?另外,当从同一个命名空间调用宏生成宏时,为什么它不会失败?