当重新加载包含 defprotocol 的命名空间时,clojure.core/proxy 无法正常工作。
例如,以下文件无法重新加载而不触发错误:
`
(ns foo.baz)
(defprotocol Hello
(hello [this]))
(def hello-proxy
(proxy [foo.baz.Hello] []
(hello []
(println "hello world"))))
(hello hello-proxy)
`
将上述内容保存为 foo/baz.clj,我得到以下错误
$ rlwrap java -cp target/clojure-1.8.0-master-SNAPSHOT.jar:. clojure.main Clojure 1.8.0-master-SNAPSHOT user=> (require 'foo.baz :reload) hello world nil user=> (require 'foo.baz :reload) CompilerException java.lang.IllegalArgumentException: No implementation of method: :hello of protocol: #'foo.baz/Hello found for class: foo.baz.proxy$java.lang.Object$Hello$6f95b989, compiling:(foo/baz.clj:11:1)
我正在使用当前的 git master(提交 5cfe5111ccb5afec4f9c73),但 clojure 1.7 也存在相同问题。
问题是 proxy-name 只使用接口名称作为键。当重新加载命名空间时,这些名称不会改变,但接口本身是新的。
我将附上一个短补丁,它可以解决我的问题。