gpt4 book ai didi

macros - 从另一个命名空间调用的宏生成宏::无法引用不存在的合格变量

转载 作者:行者123 更新时间:2023-12-01 22:46:49 24 4
gpt4 key购买 nike

我有一个宏生成宏,我试图从另一个 namespace 调用它,但它失败并显示“无法引用不存在的合格变量”。

我设法在下面的代码中重现它,这是说明问题的最简单的可能。我还找到了解决方法,但是我想了解问题的原因以及是否存在更好的解决方案。

问题

文件 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”,没有任何提示。

那么,第一种情况出了什么问题,是否有另一种方法可以修复它,更改宏生成宏以接受要生成的宏的名称作为参数?另外,为什么从同一命名空间调用宏生成宏时不会失败?

最佳答案

如果您希望宏将符号引入到运行它的命名空间中,而不是写入它的命名空间中,则可以使用 unquotequote< 的组合 让 defmacro 在宏扩展时生成一个普通的非限定符号

(ns foo)
(defmacro create-my-macro []
`(defmacro ~'my-macro []
nil))

boo> (my-macro)
nil

(symbol macroName)的调用通过从字符串创建一个非命名空间限定的符号来完成几乎相同的事情。您可以在第一个示例中使用相同的表单:

(defmacro create-my-macro []
`(defmacro ~(symbol "my-macro") []
"new-result"))

boo> (my-macro)
"new-result"

关于macros - 从另一个命名空间调用的宏生成宏::无法引用不存在的合格变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15119351/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com