参加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
by
选中 by
...