This is a continuation of issues raised in the thread about making the core "last" function behave in a polymorphic manner.
The separation of interfaces from implementation in Java serves several purposes, but one thing it does is it allows the creation of abstract data types, i.e., a type that is defined in terms of what it can do, rather than what it is comprised of or how it is implemented. Right now, in Clojure, ISeq is an interface, and by extension, it is an abstract type. One benefit this has is that we can polymorphically dispatch, via a protocol, for example, on whether something is an ISeq. We can easily create a function that applies to anything to which you can "first" and "rest", and at the same time, we can leave the function open to extension by other types. However, once ISeq is made into a protocol (which has already been done in ClojureScript and may conceivably be done in the future in Clojure), there is a problem. No longer can you dispatch via protocols on whether something is an ISeq. In other words, by using a protocol to define ISeq. we have lost its capabilities to express an abstract data type. Protocols provide a way to polymorphically dispatch to various concrete data types but appear to lose the ability to dispatch based on the abstract data type, i.e., dispatching on what the object can *do*. A hypothetical polymorphic last function, proposed in that previous thread, is a great example of why one would want to do this. A naive implementation of a polymorphic last could take the form "(cond (vector? s) ... (seq? s) ...)", but this is a closed implementation. If we want to keep the implementation open for extension, you could use something like the protocol-based code I wrote there, but it absolutely relies on these abstract data types being represented as Java interfaces rather than other protocols. David says that in 10,000 lines of code, there hasn't yet been something that required protocols to dispatch on other protocols, but in nearly the same breath he says that a polymorphic last function is impractical because of this limitation. The difficulty, he notes, is that a hypothetical ILast protocol can't be made to automatically work for all implementers of ISeq. Every single person who ever wanted to implement ISeq would also have to implement ILast. I would argue that as soon as you're ruling out ideas such as a polymorphic last function specifically because it would make it too difficult to maintain in a protocol-based system, that is clear evidence that indeed, we *are* running into a real limitation of protocols. So, I would like to better understand this limitation, and brainstorm with everyone about workarounds. I have some thoughts and ideas about this, but I want to better understand the ClojureScript architecture first. David, could you walk me through the implementation of nth, which is a very similar kind of function? I was able to find the part of the code on Github where you define an IIndexed protocol which provides a protocol for nth. However, I was unable to find the place in the code where you implement nth in linear time for all those who implement ISeq and faster for random-access collections. Can you point me to the relevant source code? Is nth open to extension to other abstract data types? Is nth guaranteed to work and gain the default implementation for new data types that implement ISeq? Do coders need to remember to implement IIndexed any time ISeq is implemented, and if so, how is that documented? Thanks! -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en