Is there a documented way to find which protocols are implemented by a Clojure object? The other way around (show for which classes a given protocol is extended) is easy: (extenders protocol).
3 Answers
I ended up with the following implementation:
(defn protocol? [maybe-p]
(boolean (:on-interface maybe-p)))
(defn all-protocols []
(filter #(protocol? @(val %)) (ns-publics *ns*)))
(defn implemented-protocols [sym]
(filter #(satisfies? @(val %) sym) (all-protocols)))
First it looks for all the symbols in the current namespace (you can of course extend this to all namespaces) whether they are protocol definitions or net (all-protocols). Next it looks for a given symbol if it satisfies one of these protocols.
The protocol? function uses the :on-interface key which isn't documented afaik, so this function is not portable.

- 9,789
- 2
- 36
- 53
-
`protocol?` fails on a sorted-map, at least in Clojure 1.8. See [this question](http://stackoverflow.com/q/37410580/1393162). – Ben Kovitz May 24 '16 at 10:22
I can't actually try this at the moment, but you might want to try the Java class method: getGenericInterfaces
. This should give you a list of interfaces. There are probably other ways to get this information using similar methods but I haven't looked.
If you also look at the source code you'll see how protocols are set up (you can get to the source by clicking on the links in the clojure api). In Clojure 1.3 there is a 'private' function that looks like this:
(defn- protocol?
[maybe-p]
(boolean (:on-interface maybe-p)))
This function is used by Clojure's extend
function to check that you've actually provided a Protocol. If you make your own function like that you can filter the results of getGenericInterfaces
. Since this is an internal detail it might be subject to change.

- 326
- 1
- 8
-
getGenericInterfaces gives me (clojure.lang.IObj clojure.lang.ILookup clojure.lang.IKeywordLookup clojure.lang.IPersistentMap java.util.Map java.io.Serializable) but not the implemented protocol. I guess I will have to delve into the source code to see how it is done. – Maurits Rijk Jan 11 '11 at 16:53
-
Just got back to my machine, and I'm not getting any further than you are. It's probably simpler to use `getInterfaces` as a reasonable alternative to `getGenericInterfaces`. I'm wondering what happens if you AOT compile the thing. – hutch Jan 11 '11 at 19:48
-
2Part of the point of protocols is that a class need not implement an interface to extend a protocol: you can define your own protocol and then say that some pre-existing class extends it with `(extend ExistingClass MyProtocol ...)`. Thus it is natural to have a way to ask "what classes extend this protocol" but not a way to ask the inverse question. – Jouni K. Seppänen Jan 12 '11 at 17:01
-
@Jouni: thanks, your answer makes sense to me. The only possible solution would then be to somehow get a list of all protocols and check if a certain Class implements it by using (extenders ...) – Maurits Rijk Jan 13 '11 at 10:35
Old question, and there is an accepted answer... however I would perhaps do something like this:
(defprotocol FooP
(foo [this]))
(defrecord Foo []
FooP
(foo [this] :whatever))
if you know the protocol that you want to check, then you can use satisfies?
> (satisfies? FooP (->Foo))
true
If not, then you could at least find all interfaces using the following
(defn interfaces [o]
(for [interface (.getInterfaces (class o))]
(.getCanonicalName ^Class interface)))
which you can check
> (interfaces (->Foo))
("com.beoliver.FooP" "clojure.lang.IRecord" "clojure.lang.IHashEq" "clojure.lang.IObj" "clojure.lang.ILookup" "clojure.lang.IKeywordLookup" "clojure.lang.IPersistentMap" "java.util.Map" "java.io.Serializable")
> (interfaces [])
("clojure.lang.IObj" "clojure.lang.IEditableCollection" "clojure.lang.IReduce" "clojure.lang.IKVReduce")
> (interfaces {})
("clojure.lang.IObj" "clojure.lang.IEditableCollection" "clojure.lang.IMapIterable" "clojure.lang.IKVReduce")
If you map bean
over the interfaces insead of calling .getCanonicalName
you will be able to see all of the options.

- 5,579
- 5
- 36
- 72