2024年的Clojure状态调查!中分享你的想法。

欢迎!请查看关于页面以了解有关此内容的更多信息。

+6
在小分类 错误
描述用户界面问题

当抛出异常且堆栈跟踪中存在多方法时,不会在调用栈中显示多方法的名称。

当我执行此代码


(defmulti dispatcher (fn [item] (:type item)))

(defmethod dispatcher "cat"
  [{:keys [lives]}]
  (/ lives 0))

(dispatcher {:type "cat" :lives 9})
*e


我得到以下堆栈跟踪


[clojure.lang.Numbers divide "Numbers.java" 163]
[clojure.lang.Numbers divide "Numbers.java" 3813]
[config_compilation.core$eval20467$fn__20469 invoke "/Users/marc/dev/circleci/orb-registry/server/src/config_compilation/core.clj" 198]
[clojure.lang.MultiFn invoke "MultiFn.java" 229]
... 省略 ...


函数名称是 {{config_compilation.core$eval20467$fn__20469}}。

如果我用 {{defn}} 直接声明 {{dispatcher}},我得到以下堆栈跟踪


(defn dispatcher
  [{:keys [lives]}]
  (/ lives 0))

(dispatcher {:type "cat" :lives 9})
*e



[clojure.lang.Numbers divide "Numbers.java" 163]
[clojure.lang.Numbers divide "Numbers.java" 3813]
[config_compilation.core$dispatcher invokeStatic "/Users/marc/dev/circleci/orb-registry/server/src/config_compilation/core.clj" 202]
[config_compilation.core$dispatcher invoke "/Users/marc/dev/circleci/orb-registry/server/src/config_compilation/core.clj" 200]
... 省略 ...


函数名称正确地给出为 {{config_compilation.core$dispatcher}}。

我猜测问题可能是 {{defmulti}} 宏没有设置 {{:name}} 元数据,或者可能没有正确地将 {{:name}} 元数据传递给编译器。

4 个答案

0
_由 alexmiller 发表的评论_

所以,如果你深入了解这些细节,这很有趣。从技术上讲,在异常发生时,defmulti 不在堆栈上(那是派发函数,它已经完成),但 defmethod 在。

defmethods 实际上是作为 fn 定义的,通常被视为匿名 fn,尽管实际上可以独立命名它们。


用户=> (defmulti 分发器 (fn [项目] (:类型 项目)))
'用户/分发器
用户=> (defmethod 分发器 "猫" 猫方法
         [{:keys [生命值]}]
         (/ 生命值 0))
#对象[clojure.lang.MultiFn 0x6e1d4137 "clojure.lang.MultiFn@6e1d4137"]
用户=> (分发器 {:类型 "猫" :生命值 9})
算术异常 除以零  clojure.lang.Numbers.divide (Numbers.java:163)
用户=> (pst *e 5)
算术异常 除以零
    clojure.lang.Numbers.divide (Numbers.java:163)
    clojure.lang.Numbers.divide (Numbers.java:3813)
    user/eval155/cat-method--157 (NO_SOURCE_FILE:11)         ;; <== 猫方法
    clojure.lang.MultiFn.invoke (MultiFn.java:229)
    user/eval161 (NO_SOURCE_FILE:12)


我认为最好的做法是如果 defmethod 函数默认使用 defmulti 函数的名称作为唯一名字(如果没有指定名称)。
0

由 alexmiller 发表评论

CLJ-2212 有关

0

由 marc 发表评论

哦,很有趣。

在这种情况下,识别多方法的符号(分发器)加上某种字符串形式的分派值将是一个非常不错的选择。

所以你可能会有这样的函数名
分发器-默认分发器-猫等。

我假设你可能还需要在末尾添加一些额外的唯一后缀。

0
...