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