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