I think Tassilo's ideas about extenders deserve more discussion. But let me 
continue the discussion with Armando for now.

Thank you for offering the Eclipse API example, which is very helpful. I 
agree that Java's OO paradigm creates the need for abstract classes. 
However, I would like to look further at what is going on in the Eclipse 
example and consider if protocols in Clojure are the same or different.

To clarify the example: Eclipse allows the user to add the user's own 
methods for certain kinds of event-handling. Because the language is Java, 
these methods must be attached to a class. In order for Eclipse to specify 
which methods it expects, Eclipse provides an interface that the user's 
class must implement. For convenience, Eclipse also provides default 
implementations of the required methods; these are provided in an abstract 
class. When the user extends this abstract class, the user can elect to 
override none, some, or all of the default methods.

I have a few observations.

1) In the example, it is certainly true that the user may implement none or 
just some of the methods of the interface. However, when the user finally 
passes an object instance to Eclipse, *all* of the methods of the interface 
are in fact implemented by that instance. This is because the default 
implementations in the abstract class will fill any holes the user leaves. 
Therefore, I respectfully disagree that this is case of "partial 
implementation." It may appear so to the user, but not to the language.

2) It is true that a Java abstract class can partially implement an 
interface. However, an abstract class cannot be instantiated. It must be 
extended first. When extending an abstract class, the user must implement 
any methods that the abstract class has not implemented. No concrete class 
"partially implements" an interface.

To me, the analogy to Java therefore supports the idea that the extends? 
relationship ought to require a datatype/record to implement all of its 
protocols' methods. A datatype/record is a piece of data, not a collection 
of default methods; it is therefore like an object instance, not an 
abstract class. Object instances must implement all of their interfaces' 
methods.

As I said in my last post, it would seem strange for a language to provide 
protocols (rather than just fast, un-grouped multimethods) if a piece of 
data that "satisfies" a protocol does not necessarily implement even one of 
the protocol's methods.

3) Armando's worry is valid that requiring implementation of protocol 
methods would result in "proliferation of interfaces and protocols that 
would prevent reuse; something like 
ListWithoutModificationOrBulkOperations." 

However, to me the beauty of protocols is that they can be highly granular. 
They are not tied to a rigid inheritance paradigm. They support direct 
implementation composition. If, per Armando's example, a protocol designer 
felt the need to have a BasicList protocol, a ModifiableList protocol, and 
a BulkOperations protocol, to be combined as necessary, that would be just 
fine. 

4) In /The Joy of Clojure/, a few of the examples involve extending a type 
to implement just one of a protocol's multiple methods (pp. 193-195). The 
authors consider this a valid use case. To leave the /JoC/ examples roughly 
intact while giving protocols a bit more bite, let me throw out two ideas 
for discussion.

Idea 1
======

Types may be extended to a strict subset of a protocol's methods, but 
satisfies? and extends? will return FALSE, not true, in this case. That is:

=> (defprotocol Fixo
     (fixo-push [fixo value])
     (fixo-pop [fixo]))
Fixo
  
=> (extend-type clojure.lang.IPersistentVector
     Fixo
     (fixo-push [vector value]
       (conj vector value)))
[succeeds]    

=> (extends? Fixo clojure.lang.IPersistentVector)
FALSE, not true


Idea 2
======

Types may be extended to new protocols only if *all* of the protocol's 
methods are implemented. However, types may be always extended tonew, 
ungrouped *methods*. That is:

=> (defprotocol Fixo
     (fixo-push [fixo value])
     (fixo-pop [fixo]))
Fixo
  
=> (extend-type clojure.lang.IPersistentVector
     Fixo
     (fixo-push [vector value]
       (conj vector value)))
[should FAIL - protocol name not allowed here unless all methods are 
implemented]  

=> (extend-type clojure.lang.IPersistentVector
     nil
     (fixo-push [vector value]
       (conj vector value)))
[should SUCCEED - fixo-push is like a fast multimethod, without a named 
protocol]

=> (extends? Fixo clojure.lang.IPersistentVector)
FALSE, not true


I invite discussion and criticism.

All the best, Garth


On Thursday, March 8, 2012 11:24:42 AM UTC-5, Armando Blancas wrote:
>
> (Don't know why I can only respond to the first message.)
>
> I come across partial implementation all the time, and with proxy, too. In 
> Eclipse this is so common that this is typical:
>
> "This adapter class provides default implementations for the methods 
> described by the SelectionListener interface.
> Classes that wish to deal with SelectionEvents can extend this class and 
> override only the methods which they are interested in."
>
> You may have seen the idea of optional operation in java.util.List and how 
> it's handled in places like AbstractList with default implementations. 
> Clojure itself has partial implementations of List in PersistentList and 
> Collection in PersistentQueue. I suppose the alternative would be a 
> proliferation of interfaces and protocols that would prevent reuse; 
> something like ListWithoutModificationOrBulkOperations could have a full 
> implementation but little use.
>
> I can see the value of your view of protocol as spec, but maybe for 
> domain-realted concepts and less for plumbing. 
>

-- 
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

Reply via email to