Trait-like behavior with Protocols

15 views
Skip to first unread message

aria42

unread,
Feb 8, 2010, 6:13:35 PM2/8/10
to Clojure
Is it possible to have default implementations associated with
functions in a protocol? This is most useful when some protocol
functions are defined in terms of other. For instance,

(defprotocol Span
(start [self])
(stop [self])
(span-length [self]))

Now I know I can just make span-length a function on Span as opposed
to part of the protocol. Is that what one should do?

Stuart Sierra

unread,
Feb 8, 2010, 8:14:19 PM2/8/10
to Clojure
On Feb 8, 6:13 pm, aria42 <ari...@gmail.com> wrote:
> (defprotocol Span
>   (start [self])
>   (stop [self])
>   (span-length [self]))
>
> Now I know I can just make span-length a function on Span as opposed
> to part of the protocol. Is that what one should do?

Yes.

-SS

Dan Larkin

unread,
Feb 8, 2010, 9:05:40 PM2/8/10
to clo...@googlegroups.com

Can you show me what this looks like?

Thanks,
Dan

Meikel Brandmeyer

unread,
Feb 9, 2010, 2:04:23 AM2/9/10
to Clojure
Hi,

The last time I checked, it was my understanding the mix-ins are used
for this.

(defprotocol Thing (abc []) (xyz []))

(def AThing {:abc (fn [] ...) :xyz (fn [] ....)})

(deftype Banana ...)

(extend Thing Banana (merge AThing {:abc (fn []...)}))

This would effectively use the "default" implementation of xyz and
provide a custom one for xyz.

But I'm not up-to-date with the protocol stuff.

Sincerely
Meikel

Jeff Rose

unread,
Feb 9, 2010, 3:41:11 AM2/9/10
to Clojure
I think the extend function is made exactly to support the concrete
implementation of protocols. It takes a type, and then any number of
protocol + function map pairs, where keyword names map to functions.
Checkout the protocol docs on assembla and look for extend:

http://www.assembla.com/wiki/show/clojure/Protocols

or read a recent post by Rich where he talks about some of the design
decisions behind these constructs:

http://groups.google.com/group/clojure/msg/330c230e8dc857a9

-Jeff Rose

On Feb 9, 12:13 am, aria42 <ari...@gmail.com> wrote:

Konrad Hinsen

unread,
Feb 9, 2010, 9:01:14 AM2/9/10
to clo...@googlegroups.com

I would say "it depends".

I have a similar situation in my multiarray package (http://code.google.com/p/clj-multiarray/). In the multiarray protocol, I have two functions, "shape" and "rank", with the latter being by definition the same as (comp count shape). However, I still have "rank" in the protocol, because for some implementations it is more efficient to compute the rank directly, rather than construct a shape vector just for computing its length afterwards.

In such situations it is useful to provide a default implementation and leave it up to each type to implement a more efficient alternative or not. With extend and the maps that go with it, this is easy to achieve: make a map with the default implementations, and merge this with the type-specific implementations fed to extend.

Konrad.

aria42

unread,
Feb 9, 2010, 4:29:16 PM2/9/10
to Clojure
If this situation is common enough, shouldn't defprotocol support
optional implementations which are implicitly merged?

Konrad Hinsen

unread,
Feb 10, 2010, 2:45:45 AM2/10/10
to clo...@googlegroups.com
On 9 Feb 2010, at 22:29, aria42 wrote:

> If this situation is common enough, shouldn't defprotocol support
> optional implementations which are implicitly merged?

Yes, if it is common enough. It's perhaps too early to decide.

Konrad.

Reply all
Reply to author
Forward
0 new messages