目前,虽然可以将协议扩展到多个接口,但没有类似于 prefer-method 的机制来优先选择一个实现方案,结果,如果多个接口匹配,则随机选择一个。
其中一个特定的问题示例是尝试处理泛型记录和映射(这在 tools.analyzer 中出现):当扩展协议到 IRecord 和 IPersistentMap 时,无法使 IRecord 实现方案被优先于 IPersistentMap 实现方案,因此无法使用协议。
附加的补丁添加了一个类似 prefer-method 但用于协议的 prefer-proto 函数。
如果从不使用 prefer-proto,则不会出现性能损失;如果使用 prefer-proto,那么在第一次协议方法分派期间查找优先级表将会有损失,但是协议方法缓存会消除后续调用的损失。
示例
user=> (defprotocol p (f [_])) p user=> (extend-protocol p clojure.lang.Counted (f [_] 1) clojure.lang.IObj (f [_] 2)) nil user=> (f [1]) 2 user=> (prefer-proto p clojure.lang.Counted clojure.lang.IObj) nil user=> (f [1]) 1
补丁: 0001-CLJ-1807-add-prefer-proto.patch