On Monday, October 8, 2012 1:55:50 PM UTC-4, Tassilo Horn wrote:
>
> Paul Stadig <pa...@stadig.name <javascript:>> writes: 
>
> Hi Paul, 
>
> > I created a library for Clojure to do open, single dispatch 
> > polymorphism. What does this mean? 
> > 
> > * A polyfn dispatches on the type of its first argument. 
> > * You can add an implementation for a new type to an existing polyfn. 
> > * You can define a new polyfn on an existing type. 
> > 
> > Polyfns are exactly as fast as protocol functions (I am using the same 
> > caching and dispatch code), but they do not generate a Java interface, 
> > and they are slightly simpler to define. 
>
> Sounds cool. 
>
> I have a bunch of mostly one-method-protocols that I extend upon 
> existing (95% java) types.  I don't rely on the existence of the 
> protocol interfaces, and neither do I use extends?, satisfies?, or 
> extenders. 
>
> Would it make sense to switch to polyfns?  Are there more advantages 
> except from the definitions being slightly more concise?
>

I can't say that you should necessarily switch to polyfns, but this was the 
kind of situation I was imagining. polyfns are the fast and open type based 
dispatch decomplected from protocols, and I think that's the main 
advantage, simplicity.

A drawback with polyfns is there's no Java interface that can be extended 
in Java code to participate in the dispatch. The Java interface is nice, 
but as you mention below, the generation of interfaces can cause staleness 
issues especially when paired with defrecord. defprotocol and defrecord 
both generate a new class each time you compile them, because of the way 
classes, class loaders, and class identity work.

Another difference between protocols and polyfns is that everytime you 
compile a defprotocol form it regenerates the protocol functions, whereas a 
polyfn is generated once and never changes (only the dispatch table 
changes). This has implications though I'm not sure how much they matter. 
YMMV

One minor problem I have with the protocol approach is that if you 
> recompile a protocol during interactive development, then calling the 
> protocol methods on already existing instances in your repl session of 
> types on which the protocol has been extended won't work anymore.  Do 
> polyfns help there? 
>

defrecord will behave differently depending on how you extend the protocol. 
If you extend the protocol inline in the defrecord form, then the class 
that defrecord generates will implement the protocol interface. In this 
case nothing gets added to the protocol dispatch table, and instead 
dispatch happens through the Java interface. When you recompile the 
defprotocol form, it regenerates the Java interface and the protocol 
functions. The new functions it generates know only about the new 
interface, so they complain when you give it an instance of your defrecord 
that you had stashed away before you recompiled.

If you define a defrecord and extend a protocol to it using extend-protocol 
or extend-type it adds an entry to the dispatch table for the protocol. 
Since dispatch happens through the dispatch table instead of the interface, 
then when you recompile your defprotocol and defrecord your old instances 
continue to work, but because of the way class identity works they continue 
to dispatch to the implementation of the protocol that was defined when you 
created your instance. In order to invoke the new implementation of the 
protocol, you need to create a new instance of your defrecord. Every time 
you recompile your defrecord it adds a new entry to the protocol's dispatch 
table, so the table will contain a number of entries on the order of the 
number of times you have recompiled your defrecord.

Since polyfns do not generate a Java interface through which they dispatch, 
they will behave like this second case. Your old instances will continue to 
work, but with the polyfn implementation that was associated with the 
instance's class, and your dispatch table size will be on the order of the 
number of times you have recompiled the polyfn forms.

I'm not sure if this is better or worse than what happens in the first 
case, but I do know that in 100% of the cases where I've used protocols I 
have not really needed the Java interface. Though it also doesn't really 
hurt anything to have the interface around if you're not using it.

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