Clojure 编译器似乎在编译函数调用时使用 vars 的 :arglists 元数据,这种方式与在它们的 defn 形式体中递归调用的函数冲突。
一个最小示例
(defn foo
{:arglists (list '[n])}
[n]
(if (even? n)
n
(foo (dec n))))
导致编译错误
语法错误(ClassCastException)在 (REPL:6:5) 编译 foo 时。无法将类 clojure.lang.Symbol 转换为类 clojure.lang.IPersistentVector(clojure.lang.Symbol 和 clojure.lang.IPersistentVector 在加载器 'app' 的未命名模块中)
在解析对 foo 的调用时,编译器似乎使用了未求值的参数列表形式 (list (quote [n]))
,由于符号 list
不是一个预期的参数向量,因此抛出异常。
这是一个更真实示例的例子,这种情况可能会发生
(def ^:private shape-attrs
'{:keys [height width color]})
(defn draw
{:arglists (list ['shape]
['shape shape-attrs])}
([shape]
(draw shape {:color "black"}))
([shape attrs]
:ok))