这是一个来自clojure的喜悦的例子:
(let [x 9, y '(- x)]
(println `y)
(println ``y)
(println ``~y)
(println ``~~y))
来自repl的输出:
typedclj.macros/y
(quote typedclj.macros/y)
typedclj.macros/y
(- x)
如果我重新排列引用/取消引用的顺序,结果仍然相同(我想知道为什么):
(let [x 9, y '(- x)]
(println `y)
(println ``y)
(println `~`y)
(println `~`~y))
但如果我把波浪号放在前面:
(let [x 9, y '(- x)]
(println `y)
(println ``y)
(println `~`y)
(println ~``~y))
我收到一个奇怪的错误:
CompilerException java.lang.IllegalStateException: Attempting to call unbound fn: #'clojure.core/unquote, compiling:(/Users/kaiyin/personal_config_bin_files/workspace/typedclj/src/typedclj/macros.clj:1:25)
为什么我会收到此错误?
答案 0 :(得分:1)
简短回答:你在unquote
之外尝试syntax-quote
,这没有意义。
更多详情:
此错误是从最终的println生成的。观察
(println ~``~y)
扩展为
(println (unquote (syntax-quote (syntax-quote (unquote y))))
这种情况发生在~
并且反引号字符是读者宏。扩展unquote
实际上不是正常函数或宏。它是一种特殊形式,仅在syntax-quote
内定义。您可以在LispReader.java中的编译器源中看到这一点。当你在syntax-quote
形式之外使用它时,读取器宏仍然发生但是没有“unquote”这样的功能。 core.clj中只有一个裸(def unquote)
(第一个定义)。
当您执行def
之类的操作时,最终会得到一个var,其初始绑定是类cloure.lang.Unbound
的一个实例(它是clojure.lang.Var
上的constructors之一这个子类clojure.lang.AFn
但没有指定任何arities;所以每次调用它都会调用throwarity
,给你这个例外。