不清楚你使用的 Clojure 或编辑器版本,但 Clojure 1.10.3 在标准 repl 中提供了更有用的输出。
user=> (macroexpand '(m))
Syntax error macroexpanding clojure.core/fn at (REPL:1:1).
(user/x) - failed: Extra input at: [:fn-tail :arity-1 :params] spec: :clojure.core.specs.alpha/param-list
user/x - failed: vector? at: [:fn-tail :arity-n :params] spec: :clojure.core.specs.alpha/param-list
如你所见,在遇到问题时不是运行你的代码,而是(递归地)宏展开。第一次展开将变成
(clojure.core/fn [user/x])
clojure.core/fn
本身是一个宏,会在扩展过程中展开。在这个过程中,fn
宏会被检查是否符合 fn
规范(默认启动宏的规范检查)。规范会找到 user/x
并将其视为 :params
中的 "额外输入",因为它不符合任何预期的参数形式(通常是未命名的符号,但也包括所有递归分解形式)。实际上,问题是出在 user/x
而不是 x
上。
您可以使用以下方法修复它:
(defmacro m []
`(fn [~'x]))