Interesting project, although I'm still a little unclear about the "convincing" use cases where you would choose polyfn over protocols...
Also, how does the polyfn implementation compare to the clojurescript protocol implementation? -FrankS. On Oct 8, 2012, at 7:17 PM, Paul Stadig <p...@stadig.name> wrote: > On Monday, October 8, 2012 1:55:50 PM UTC-4, Tassilo Horn wrote: > Paul Stadig <pa...@stadig.name> 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 -- 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