Given some type or record, how can I get all the protocols it implements?
Let's say we have the following code:
(defprotocol P1
(op1 [this]))
(defprotocol P2
(op2 [this]))
(defrecord R []
P1
(op1 [_] 1)
P2
(op2 [_] 2))
And what I need is a function that does something like this:
(all-protocols-for-type R) ;; => (P1 P2)
It will be good if there's something backend-agnosting, because I'd like to have a mechanism for both Clojure and ClojureScript.
UPD: the intention for this is to introspect what functionality the particular type provides. Let's say, by doing this:
user> (supers (type {}))
#{clojure.lang.AFn clojure.lang.ILookup java.lang.Object java.util.Map clojure.lang.Seqable java.lang.Runnable clojure.lang.IPersistentCollection java.io.Serializable clojure.lang.IFn clojure.lang.APersistentMap clojure.lang.Associative java.util.concurrent.Callable clojure.lang.IKVReduce clojure.lang.Counted clojure.lang.IMeta clojure.lang.IMapIterable java.lang.Iterable clojure.lang.IPersistentMap clojure.lang.IEditableCollection clojure.lang.IObj clojure.lang.MapEquivalence clojure.lang.IHashEq}
I will know that I can use map as a function (IFn
), lookup a value by key there (Associative
) and even do reduce-kv
on it (IKVReduce
).
This is the closest you can get in Clojure without doing something crazy:
I used that specific
map
just to get an output with the same format you gave in your question; you should modify the mapping function as you see fit.Basically, what you're asking is the other side of the coin to this. Extension of a protocol using
deftype
ordefrecord
stores the information on the type, and extension usingextend-type
orextend-protocol
stores the information on the protocol.So if all your extensions are done directly in
deftype
ordefrecord
, you can get all the protocols for a given type using the method I gave above. If all your extensions are done withextend-type
orextend-protocol
, you can get all the types for a given protocol using the method Alex gave in his answer to that other question. But there isn't a nice way to do both in all cases.This is not possible in general, on the JVM at least, since extending a type to a protocol leaves no information on the type, only on the protocol. In clojurescript I'm not sure. Why do you want this? It's not really very useful to have a list of protocols, if you don't even know what those protocols are for.
I can't possibly think of any real world utility of a list of protocols implemented for a type, unless this list will be compared to another list of protocol references.
If the protocol references (in the 2nd list) is known the following would do:
If the goal isn't to compare against a list of protocols, please update the question with the actual use case.