繁体   English   中英

IllegalStateException:尝试在宏中调用未绑定的fn

[英]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-afn-c的调用有效,但是当fn-c尝试调用fn-b我得到IllegalStateException:试图调用未绑定的fn:#'name.space / fn-b 这是为什么?

如果我把fn-bfn-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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM