Question

I've been experimenting a lot with extending Clojure's protocols to already existing types, but it seems like whenever I have a question like "How would I extend this protocol to all seq-able collections?" or "How would I extend this protocol to all numbers (longs, ratios, integers, floats, etc.)?" I have to do a lot of googling to find the answers, and even then, I'm not always able to find a definitive answer.

Is anyone aware of a handy reference for commonly used clojure.lang.Something, java.lang.SomeJavaClass, etc. classes and protocols? I think it would be beneficial if we had some resource available to help out the Clojurians like myself who have little to no Java experience.

EDIT: To give you an idea of what I'm looking for, in this code:

(defprotocol X
  (do-something [this]))

(extend-protocol X
  ?????? <-- 
  (do-something [this] '(implementation goes here)))

Is there a resource that might have a list of Clojure/Java classes to which it might be useful to extend a protocol?

Was it helpful?

Solution

No direct answer here, but some useful resources:

  • I find Stuart Sierra's class diagram project to be hugely useful for visualizing the class structure of Clojure and Java interfaces it depends on.
  • Chouser has some older static diagrams here
  • If you are creating custom collections via deftype, this scaffolding macro can save you a lot of time

OTHER TIPS

I think I semi-answered my own question, although I'm still curious to know if anyone has a better solution:

For Java classes, you can start by googling e.g. "Java Integer class," and the official docs will show you the chain of inheritance up from java.lang.Integer -> java.lang.Number -> java.lang.Object. It seems that most (if not all...?) java.lang.X classes can be abbreviated within extend-protocol as just X, so Number should work for extending a protocol to all subclasses of numbers.

It seems like the online documentation for Clojure doesn't clearly show chains of inheritance like this, unless I'm missing something. But clojure.core/supers is a handy method to at least find classes to try extending a protocol to in order to get the functionality you're looking for:

user> (class [])
;=> clojure.lang.PersistentVector

user> (supers (class []))
;=> #{clojure.lang.Sequential clojure.lang.ILookup clojure.lang.AFn
      clojure.lang.APersistentVector java.util.concurrent.Callable
      java.util.RandomAccess clojure.lang.Reversible java.util.List 
      clojure.lang.IHashEq java.util.Collection clojure.lang.IMeta 
      java.lang.Object java.io.Serializable clojure.lang.Associative 
      clojure.lang.Seqable clojure.lang.IEditableCollection java.lang.Iterable 
      clojure.lang.Counted java.lang.Runnable clojure.lang.IPersistentCollection 
      clojure.lang.IObj clojure.lang.IPersistentVector clojure.lang.Indexed 
      clojure.lang.IFn clojure.lang.IPersistentStack java.lang.Comparable} 

clojure.lang.Sequential seems like a useful class for extending a protocol for which you'd like a general implemention for all sequential collections.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top