引号内的unquote-splice导致符号未找到错误

时间:2015-05-07 13:58:37

标签: clojure macros

以下是代码:

(defmacro inspect-caller-form [& args]
  {:form (quote `(inspect-caller-form ~@args))})
(inspect-caller-form 1 2 3)

和错误:

CompilerException java.lang.RuntimeException: Unable to resolve symbol: args in this context, compiling:(/Users/kaiyin/personal_config_bin_files/workspace/cina/src/cina/ref_types.clj:406:5) 

但如果我在quote之前移动语法引用,事情似乎有效:

(defmacro inspect-caller-form [& args]
  {:form `(quote (inspect-caller-form ~@args))})
(inspect-caller-form 1 2 3)

为什么?

1 个答案:

答案 0 :(得分:2)

通过简单地在repl上评估它们并查看它们评估的形式,它通常可以帮助调试语法引用问题。在这种情况下,我们可以看到第一个示例扩展为读取语法引用的未评估结果。这是因为语法引用是clojure中为数不多的读取器宏之一,并且可以在宏扩展时开始工作。然后您的报价电话会阻止它进一步扩展。所以语法引用永远不会完成它的工作。

user> (let [args [1 2 3]]
        (quote `(inspect-caller-form ~@args)))

(clojure.core/seq (clojure.core/concat 
                      (clojure.core/list 
                          (quote user/inspect-caller-form)) 
                      args))

虽然第二个允许语法引用表单完成评估,并产生一个引用调用的结果。因此,最终结果是一个单引号列表,其值已经拼接到其中。

user> (let [args [1 2 3]]
        `(quote (inspect-caller-form ~@args)))

(quote (user/inspect-caller-form 1 2 3))

在语法引用中使用引用实际上是编写宏的有用技巧,它可以将新符号直接引入调用者的范围,称为符号捕获