09:43 $ clj
Clojure 1.8.0
(defmulti foo :bar)
(defmethod foo :qix [quux znoot] (println 'hi))
#'user/foo
user=> #object[clojure.lang.MultiFn 0x205d38da "clojure.lang.MultiFn@205d38da"]
user=> (foo {:bar :qix})
ArityException 错误的参数数量 (1) 传递给:user/eval5/fn--6 clojure.lang.AFn.throwArity (AFn.java:429)
user=>
多方法是作为匿名函数实现的,这是一个实现细节。我期望错误信息至少包含失败函数的名称,在这种情况下,它应该是这样的
ArityException 错误的参数数量 (1) 传递给:user/eval5/foo--6 clojure.lang.AFn.throwArity (AFn.java:429)
可以采取几种方法来解决这个问题
第一个(也是最简单的)是更改 {{defmethod}} 的定义,使匿名函数有一个名称。
这将导致类似以下错误消息
user=> (defmulti foo :bar)
(defmethod foo :qix [quux znoot] (println 'hi))
(foo {:bar :qix})#'user/foo
user=> #object[clojure.lang.MultiFn 0x4e928fbf "clojure.lang.MultiFn@4e928fbf"]
user=>
ArityException 错误的参数数量 (1) 传递给:user/eval5/foo--6 clojure.lang.AFn.throwArity (AFn.java:429)
user=>
除此之外,还可以修改 Compiler.java 文件,查找对 "addMethod" 的调用
String prefix = "eval";
if (RT.count(form) > 2) {
Object third = RT.nth(form, 2);
if (third != null &&
"clojure.core/addMethod".equals(third.toString()))
prefix = "multi_fn";
}
ObjExpr fexpr = (ObjExpr) analyze(C.EXPRESSION, RT.list(FN, PersistentVector.EMPTY, form), prefix + RT.nextID());
这将给出类似以下错误消息
ArityException 错误的参数数量 (1) 传递给:user/multi-fn5/foo--6 clojure.lang.AFn.throwArity (AFn.java:441)