On Thu, Feb 19, 2009 at 11:34 AM, mikel <mev...@mac.com> wrote: > > I did consider it, and am still considering. I'd be interested to know > other people's opinions about the best (that is, most comfortable for > users, least out-of-place) way of providing GFs in library code.
I'm not your target audience for that question, but you bring up some other interesting questions as well... > I could certainly implement GFs by making make-generic-function return > an AFn proxy. A disadvantage of doing that (and of reoresenting GFs > as closures, as the first implentation did) is that a generic function > object then has no identity as such; that is, you can't tell from > looking at it that it's a generic function. It's some AFn proxy (or > closure) that might be anything. If you want to know whether it's a > gf, you just have to try using it as one and see what happens. On this point, would it help if you could provide a custom print for the object? This idea has come up a couple times now, and I have a toy implementation that seems indicate it could be done cleanly. It would allow your make-generic-function to return an object that would print uniquely, with whatever combination of name and closed-over data you want, independant of the specific proxy class that its an instance of. Of course calling 'class' on it would still show the goofy proxy class name, but I wouldn't expect that to be a big problem. > Another disadvantage is that, like MultiFns, generic functions have > some state. In both cases, the state is a dispatch table. The dispatch > algorithm used is different for the two types of polymoprhic > functions, but both carry around data used by dispatch, and both sort > of want you to be able to update the state (in the case of MultiFn, by > calling defmethod). You kind of want to have an equivalent for generic > functions of defmethod, and of add-method and remove-method. You can close over an atom or ref to get your mutable state. This is a mess and by itself useless, but maybe it helps show what I mean: (defn make-thing [a b] (let [state (atom {})] (proxy [clojure.lang.AFn clojure.lang.IDeref] [] (deref [] state) (invoke ([] "no arg") ([x] "one arg"))))) (def thing (make-thing 1 2)) Now you can call the thing with zero or one args: user=> (thing 1) "one arg" You can also write functions that mutate it's state. A add-method function could be defined to do something like: (swap! @thing assoc :A 1) That new value can be accessed from any of the invoke bodies, or anywhere else, actually: user=> thing #<afn$ide...@2a6ff: #<a...@21d23b: {:A 1}>> That prints ugly indeed. Rich, do you have any interest in per-object custom print fns, hanging off meta-data? > I'd be interested in opinions about what the best approach is and why. I can't say with confidence what the best approach is, I just know that much prefer the dynamic nature of proxy and when possible would rather use it. Perhaps what I outlined above is too convoluted for your taste, and I think that would be a reasonable response. I mostly want to make sure proxy is not overlooked. --Chouser --~--~---------~--~----~------------~-------~--~----~ 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 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 -~----------~----~----~----~------~----~------~--~---