Am I correct in believing that derive
, parents
, and ancestors
in clojure.core have no relationship with protocols?
yup
And if the answer is "yes", is there anything built into Clojure that is like parents
or ancestors
that takes protocols into account? (Or if that would be ill-defined or not make sense for some reason, would appreciate some hints as to why)
no, protocols have no hierarchy semantics by design
Even if no hierarchy, something like "what protocols does this class/interface implement?" could be useful to query, perhaps?
but it's not possible to do, protocol implementations belong to the protocol not to the classes/interfaces
you'd have to scan the open universe of protocols to know which ones a class extends
In Clojure/Java, I have forgotten which ways of defining an implementation of a protocol do this, but some create a "class/interface extends Java-interface-of-protocol" relationship. Those can be seen via Java reflection API, and so also parents
and ancestors
. Double checking that to make sure I am not imagining things.
yes, that happens when you implement a protocol inline in a deftype
but it's merely an optimisation/implementation detail
and crucially it's not a thing that happens in all the ways a type can extend a protocol
Understood. I was a bit confused when I first came across that. It does mean some of those relationships show up in parents
results, but not all, I think.
there is preference within protocols impls already: protocol extensions to concretions win over extensions to interfaces
are you talking about extend with meta?
oh nvm I understand what you mean
rephrased for broadcast: checking for a protocol implementation walks up the concrete hierarchy before the interfaces
I am still catching up, though 🙂 Ghadi, do you mean that if class A has an implementation for protocol P, and class A implements interface I1, and I1 has an implementation for protocol P, then calling a protocol P function on an instance of class A should always execute the class A implementation?
yes
But still, if one was creating a "does X implement/extend Y" kind of diagram, "A implements P" is true in that situation, regardless of exactly which implementation of P is used.
right -- sorry I thought the original question was about preference when there is ambiguity
So there is no central "registry" of protocols in Clojure, but if you had a list of namespaces, you could walk through all of their Vars and look for them, based on knowing what protocols "look like" in the implementation details?
(note that in the case of multiple inheritance w/o a clear derivation preference, it's undefined which impl will be used)
@andy.fingerhut yes, but at a specific point in time
I don't mind the extra detail, but I was more asking whether there is already something like parents
that, given A, would return P among the results, if A implements P
protocols can be extended a runtime
at t1 class A can not extend protocol P but at t2 it may
Well, Java classes can be loaded at runtime, too, so runtime changes don't bother me 🙂
I'm going to split hairs here @bronsa: the undefined impl case you're talking about is when you implement multiple interfaces to which the protocol is extended
Ah, I guess you mean that Java classes have their extends/implements-Java-interfaces relationships all known after the class is initialized, but protocols have another level of dynamicity beyond that?
yep
Thanks for the clarification there. FYI, the reason for my asking is that I was hoping to enhance Stuart Sierra's class-diagram library to show "implements protocol" relationships, in addition to the parents
/ ancestors
relationships that it shows now, and trying to figure out how.
i'm sure for tooling purposes it should be easy to get something working even tho it may not be correct/complete 100% of the cases
Among other enhancements that led me to look up 1970s CS algorithms papers on computing transitive reductions, which is something I've almost known how to do, but never in anger yet.
These diagrams can get visually messy pretty quickly.
No need for anyone to dig through lots of code, but as a semi-quick hack, looking through all Vars in a namespace for those whose value is a Clojure map, that contains at least the keys (:on :on-interface :sigs :var :method-map :method-builders)
, seems likely to catch everything defined via Clojure/Java defprotocol
, and while it could possibly catch other things, that seems somewhat unlikely to happen.
I could do additional sanity checks on the types/values associated with those keys, of course.
:impls
too
if you don't see :impls
that means the protocol has no extenders
I did a quick check, and :doc
and :impls
are not there when one first defines a protocol, but understood, yes.
And it does not gain a key :impls
if one creates a deftype
that implements the protocol.
yup, the extenders of an interface are an open set. (e.g. functions that return a reify
)
Thanks for that info. For the purposes of this exercise I am going through, I am looking only for protocols that a given Java class/interface implements, not necessarily all Java objects that currently exist that implement them.