arity 为 (-1) 的 ArityException
ArityException with arity of (-1)
有一个宏,我一直在努力找出这个错误 ArityException Wrong number of args (-1) passed to: user/bar clojure.lang.Compiler.macroexpand1 (Compiler.java:6557)
。我尝试调试,但我不明白为什么当我尝试扩展宏时会有 (-1) 的数量。
我是运行下面的代码
(defn foo [x] (println x))
(defmacro bar [exp]
(let [length (count exp)]
(cond
(= length 0) '()
(= length 1) exp
:else (let [[head & tail] (vec exp)
[new-tail] (bar tail)]
`(trap (~head ~@new-tail))))))
(macroexpand '(bar (inc 1)))
有人知道 (-1) 的元数是怎么回事吗?
使用 REPL 中的 *e
变量,我打印了堆栈跟踪。
clojure.lang.ArityException: Wrong number of args (-1) passed to: user/bar
Compiler.java:6557 clojure.lang.Compiler.macroexpand1
core.clj:3703 clojure.core/macroexpand-1
core.clj:3712 clojure.core/macroexpand
这指向 Compiler.java
中的 clojure.lang.Compiler.macroexpand1
方法,我在其中找到了这一行:
throw new ArityException(e.actual - 2, e.name);
如果 e.actual
是 1
,则 ArityException
构造函数的第一个参数的结果是 -1
。有一张 JIRA 票证 here 提到了这个非常令人困惑的 ArityException
消息。
根据这张票所说的内容,我开始在其他地方寻找 ArityException
,并在 count
和 vec
的使用中找到了它,就好像 exp
总是一个列表。
问题是当递归调用宏 bar
时,参数实际上是 symbol tail
而不是集合,这个调用实际上是macro-expanded 当宏本身被创建时 而不是 当它被调用时。
更改宏的代码,使其考虑未列出的可能值可以解决问题,但我认为生成的宏无法满足您的需求。
(defmacro bar' [exp]
(prn exp)
(let [length (if (seq? exp) (count exp) 0)]
(cond
(= length 0) '()
(= length 1) exp
:else
(let [[head & tail] (if (seq? exp) (vec exp) [exp])
[new-tail] (bar' tail)]
`(trap (~head ~@new-tail))))))
;; tail
(macroexpand '(bar' (inc 1)))
;; (inc 1)
;;= (user/trap (inc))
有一个宏,我一直在努力找出这个错误 ArityException Wrong number of args (-1) passed to: user/bar clojure.lang.Compiler.macroexpand1 (Compiler.java:6557)
。我尝试调试,但我不明白为什么当我尝试扩展宏时会有 (-1) 的数量。
我是运行下面的代码
(defn foo [x] (println x))
(defmacro bar [exp]
(let [length (count exp)]
(cond
(= length 0) '()
(= length 1) exp
:else (let [[head & tail] (vec exp)
[new-tail] (bar tail)]
`(trap (~head ~@new-tail))))))
(macroexpand '(bar (inc 1)))
有人知道 (-1) 的元数是怎么回事吗?
使用 REPL 中的 *e
变量,我打印了堆栈跟踪。
clojure.lang.ArityException: Wrong number of args (-1) passed to: user/bar
Compiler.java:6557 clojure.lang.Compiler.macroexpand1
core.clj:3703 clojure.core/macroexpand-1
core.clj:3712 clojure.core/macroexpand
这指向 Compiler.java
中的 clojure.lang.Compiler.macroexpand1
方法,我在其中找到了这一行:
throw new ArityException(e.actual - 2, e.name);
如果 e.actual
是 1
,则 ArityException
构造函数的第一个参数的结果是 -1
。有一张 JIRA 票证 here 提到了这个非常令人困惑的 ArityException
消息。
根据这张票所说的内容,我开始在其他地方寻找 ArityException
,并在 count
和 vec
的使用中找到了它,就好像 exp
总是一个列表。
问题是当递归调用宏 bar
时,参数实际上是 symbol tail
而不是集合,这个调用实际上是macro-expanded 当宏本身被创建时 而不是 当它被调用时。
更改宏的代码,使其考虑未列出的可能值可以解决问题,但我认为生成的宏无法满足您的需求。
(defmacro bar' [exp]
(prn exp)
(let [length (if (seq? exp) (count exp) 0)]
(cond
(= length 0) '()
(= length 1) exp
:else
(let [[head & tail] (if (seq? exp) (vec exp) [exp])
[new-tail] (bar' tail)]
`(trap (~head ~@new-tail))))))
;; tail
(macroexpand '(bar' (inc 1)))
;; (inc 1)
;;= (user/trap (inc))