The Clojure compiler appears to use the :arglists metadata of vars when compiling function invocations, in a way which conflicts with functions being called recursively in the body of their defn
form with dynamically specified metadata.
A minimal example:
(defn foo
{:arglists (list '[n])}
[n]
(if (even? n)
n
(foo (dec n))))
Which results in the compilation error:
Syntax error (ClassCastException) compiling foo at (REPL:6:5). class clojure.lang.Symbol cannot be cast to class clojure.lang.IPersistentVector (clojure.lang.Symbol and clojure.lang.IPersistentVector are in unnamed module of loader 'app')
The compiler appears to be using the unevaluated form of the arglist (list (quote [n]))
when parsing the call to foo
, throwing an exception due to the symbol list
not being the expected argument vector.
Here's a slightly more realistic example of where this could occur:
(def ^:private shape-attrs
'{:keys [height width color]})
(defn draw
{:arglists (list ['shape]
['shape shape-attrs])}
([shape]
(draw shape {:color "black"}))
([shape attrs]
:ok))