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' 加载器的匿名模块中)
编译器似乎在使用未评估的 arglist 形式 (list (quote [n]))
解析对 foo
的调用,由于符号 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))