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

欢迎!请参阅关于页面以获取更多关于此页面如何工作的信息。

+3
协议
重新标记

当前 extend-protocol 定义的函数在堆栈跟踪中看起来是这样的

at app.core$eval3547$fn__3548.invoke(core.clj:23)
at app.core$eval3522$fn__3523$G__3513__3532.invoke(core.clj:14)

不用说,这些并不非常具有描述性。更不用说它指向的行是调用 extend-protocol 和 defprotocol 的地方,而不是函数定义的位置。

我希望是像这样:app.core/MyProtocol/IfaceImplemented/函数名_1234,带有包含“恶意”代码的行的行号,而不是定义。

我在本地稍微修改了一下,发现改变 emit-method-builder、emit-impl 和 emit-hinted-impl 会让堆栈跟踪更加易读。

黑客分支差异

diff --git a/src/clj/clojure/core_deftype.clj b/src/clj/clojure/core_deftype.clj
index 786f0d4b..73570dbf 100644
--- a/src/clj/clojure/core_deftype.clj
+++ b/src/clj/clojure/core_deftype.clj
@@ -586,9 +586,10 @@
 
 (defn- emit-method-builder [on-interface method on-method arglists extend-via-meta]
   (let [methodk (keyword method)
-        gthis (with-meta (gensym) {:tag 'clojure.lang.AFunction})
-        ginterf (gensym)]
-    `(fn [cache#]
+        gthis (with-meta (gensym (str method)) {:tag 'clojure.lang.AFunction})
+        ginterf (gensym)
+        giface-name (gensym (last (.split (name on-interface) "\\.")))]
+    `(fn ~giface-name [cache#]
        (let [~ginterf
              (fn
                ~@(map 
@@ -812,9 +813,21 @@
                    (:var proto)))))
     (-reset-methods (alter-var-root (:var proto) assoc-in [:impls atype] mmap))))
 
+(defn- iface-fn-name
+  ([p f]
+   (iface-fn-name "" p f))
+  ([c p f]
+   (let [c-name (cond
+                  (symbol? c)
+                    (last (.split (name c) "\\."))
+                  (nil? c)
+                    "nil"
+                  :else nil)]
+     (symbol (str p (when c-name (str "__" c-name)) (first f))))))
+
 (defn- emit-impl [[p fs]]
   [p (zipmap (map #(-> % first keyword) fs)
-             (map #(cons `fn (drop 1 %)) fs))])
+             (map #(cons `fn (cons (iface-fn-name p %) (drop 1 %))) fs))])
 
 (defn- emit-hinted-impl [c [p fs]]
   (let [hint (fn [specs]
@@ -826,7 +839,7 @@
                               body))
                       specs)))]
     [p (zipmap (map #(-> % first name keyword) fs)
-               (map #(cons `fn (hint (drop 1 %))) fs))]))
+               (map #(cons `fn (cons (iface-fn-name c p %) (hint (drop 1 %)))) fs))]))
 
 (defn- emit-extend-type [c specs]
   (let [impls (parse-impls specs)]

日志后

at app.core$eval3965$ProtocolName__ClassName__FnName__3966.invoke(core.clj:23)
at app.core$eval3940$ProtocolName3932__3941$__FnName3930__3950.invoke(core.clj:14)

2 个答案

+1
0

可读性良好。

我隐约记得Windows会以某种方式限制包名+类名的长度。

如果该建议涉及到延长类名长度,那么它可能会使某些Clojure程序在Windows上无法正常工作。

您可以使用extend直接命名函数,所以我认为这不会成为一个真正的问题。
...