不确定您使用的是哪个版本的 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]))