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)
这里可以采用几种方法
第一种(也是 simplest)是更改`{{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)