![](/img/trans.png)
[英]Clojure macro throws “CompilerException java.lang.IllegalStateException: Var clojure.core/unquote is unbound” when called
[英]IllegalStateException: Attempting to call unbound fn in macro
我正在尝试编写一个调用某些函数的宏。 这些函数只能由宏使用,所以我将它们放在包装宏的letfn
。 伪代码:
(letfn [(fn-a [] ...)
(fn-b [] ...)
(fn-c [] (fn-b))]
(defmacro my-macro [stuff]
`(let [whatever# (fn-a)]
(fn-c))))
对fn-a
和fn-c
的调用有效,但是当fn-c
尝试调用fn-b
我得到IllegalStateException:试图调用未绑定的fn:#'name.space / fn-b 。 这是为什么?
如果我把fn-b
和fn-c
放在他们自己的defn
,一切都会奏效。 但我不想这样做,因为它不干净。
编辑:只是为了测试,我尝试将函数绑定放在内部let
但遇到了同样的异常。
我不认为这可以这么做。 例如,对fn-c
的调用扩展为your.namespace/fn-c
,因此您的代码似乎调用恰好具有相同名称的其他函数。 但你没有一个your.namespace/fn-b
,它会引发异常。
要引用一个不合格的符号,你需要引用它并取消引用它: ~'fn-a
但是这不起作用,因为本地函数没有在扩展点定义,你只能将它们用于宏本身。
您必须在命名空间中定义函数并在宏中对它们进行限定,或者将它们包含在宏展开中,这将在每次使用时再次定义它们。
我不确定这是否正是你所追求的,但如果我这样做:
(letfn [(fn-a [] (println 1))
(fn-b [] (println 2))
(fn-c [] (fn-b))]
(defmacro my-macro [stuff]
`(let [whatever# ~(fn-b)]
~(fn-c))))
然后它工作 - 它只需要波形符号来取消引用函数调用。
以下两项工作:
(defn fn-x [] (println 1))
(defn fn-y [] (fn-x))
(defmacro my-macro2 [stuff]
`(let [whatever# (fn-x)]
(fn-y)))
和
(defn fn-x [] (println 1))
(defn fn-y [] (fn-x))
(defmacro my-macro2 [stuff]
`(let [whatever# ~(fn-x)]
~(fn-y)))
在第一种情况下,正在评估函数,并且它们的结果在编译时被合并到宏中,而在第二种情况下,它们在运行时被评估。 使用letfn
(它本身就是一个宏),结果在编译时是不可用的(可能是因为它们是在编译宏之后编译的)所以这些函数只能在运行时使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.