2024 Clojure状态调查! 中分享您的观点。

欢迎!请参阅 关于 页面以了解更多关于其工作原理的信息。

+1 投票
Clojure
重新标记

如果您在 deftype 表达式中错误地多次指定一个协议,可能会省略该协议的一些方法实现。

复现

(defprotocol P (f [this]) (g [this]))

(deftype T []
  P
  (f [this] :F)
  P
  (g [this] :G))

(def t (->T))

(f t)
;; Execution error (AbstractMethodError) at user/eval187 (REPL:1).
;; Receiver class user.T does not define or inherit an implementation of the resolved method 'abstract java.lang.Object f()' of interface user.P.

(g t) ;=> :G

您可以通过宏扩展 deftype 表达式来确认一些方法实现被忽略

(macroexpand '(deftype T [] P (f [this] :F) P (g [this] :G)))
;=> (let* [] (deftype* user/T user.T [] :implements [user.P clojure.lang.IType] (g [this] :G)) (clojure.core/import user.T) (clojure.core/defn ->T "Positional factory function for class user.T." [] (new user.T)) user.T)

根本原因似乎是 parse-impls

(#'clojure.core/parse-impls '(P (f [this] :F) P (g [this] :G)))
;=> {P ((g [this] :G))}

在我看来,如果 deftype 能够检查是否重复指定了相同的协议,并在这种情况抛出错误,那会很好。否则,我认为不应在没有警告的情况下忽略方法实现。

1 答案

+1 投票

选中
...