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());
}
which would give us error messages like