Share your thoughts in the 2021 Clojure Community Survey!

Welcome! Please see the About page for a little more info on how this works.

0 votes
in Protocols by

Currently it's possible to extend a protocol to multiple interfaces but there's no mechanism like prefer-method for multimethods to prefer one implementation over another, as a result, if multiple interfaces match, a random one is picked.

One particular example where this is a problem, is trying to handle generically records and maps (this come up in tools.analyzer): when extending a protocol to both IRecord and IPersistentMap there's no way to make the IRecord implementation be chosen over the IPersistentMap one and thus protocols can't be used.

The attached patch adds a prefer-proto function that's like prefer-method but for protocols.

No performance penalty is paid if prefer-proto is never used, if it's used there will be a penalty during the first protocol method dispatch to lookup the perference table but the protocol method cache will remove that penalty for further calls.

Example:

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

Patch: 0001-CLJ-1807-add-prefer-proto.patch

1 Answer

0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJ-1807 (reported by bronsa)
...