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 的调用时使用了未求值的 arglist 的形式 (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))