On Dec 7, 9:07 am, Laurent PETIT <laurent.pe...@gmail.com> wrote: > 2009/12/7 Hugo Duncan <hugodun...@users.sourceforge.net> > > > On Mon, 07 Dec 2009 06:53:38 -0500, Rich Hickey <richhic...@gmail.com> > > wrote: > > > > Yes, methods are not really functions. Thinking about them as closures > > > over the object is a good way to go - you can see that analogy in play > > > when you consider recur, which works with these methods, but could not > > > rebind 'this'. The recur case sealed the deal in the decision not to > > > include 'this' in the argument lists. > > > I had a quick play with protocols, and the biggest problem I had getting > > started was realising that the signature of a method definition in > > defprotocol was different to the signature required to implement the same > > method in deftype. FWIW, I found it very non-intuitive. > > Hello, > > And now that you've got it, do you still feel this non-intuitive. > Because I had the same feeling first: I thought I would never rembember how > things work and why put 'this-like args there, and not there ... > But now that everything "clicked in place", I feel the last status of what > Rich achieved to do the most natural and intuitive. > > Basically, what helped me was along the lines of what Konrad said : > * defprotocol and extend are "purely functional" : so you have to specify > every argument, including the object the functions acts upon. > * deftype with embedded protocol definition for the type, or reify, in the > contrary, do not define pure functions. They define methods. You cannot get > them as values and pass them around like higher-order functions, for > example. And you must know this fact, it cannot be an implementation detail. > So, since you know this fact, you remember that you're in a method > definition (in the general sense of object oriented languages : method of a > class) and, as you do with e.g. java, C#, ... , when definining methods, you > do not add the target of the method as an implicit argument. > > The big advantage I see to this is that once you get it, you don't have > anymore to remember where 'this is explicit and where it's implicit: it's > intuitive. > The other big advantage is that the use of recur inside these > functions/methods bodies continue to match exactly the signature of the > function/method (otherwise you would have had to remember that, e.g. in > methods defined via deftype, you must place an explicit "this" argument in > the method arg list, but not place it in the recur calls ... :-( ) > > HTH, > > -- > laurent
That was my experience as well. It started off as a gotcha (since I was copy/pasting the protocol definitions over to the deftype), but then after playing for a bit it wasn't a big deal. In all my usages so far I haven't needed to reference 'this'. The one area I am running into issues is with being able to provide a default implementation, or extending types such that I can override a method. For example, I have: (defprotocol http-resource (GET [res req resp]) (POST [res req resp]) (PUT [res req resp]) (DELETE [res req resp]) (HEAD [res req resp]) (OPTIONS [res req resp]) (TRACE [res req resp])) But I considering the usage, most of those need not be implemented per- type, and could all be defaulted to something like: (deftype resource [] http-resource (GET [req resp] (send-status! resp 405)) (POST [req resp] (send-status! resp 405)) (PUT [req resp] (send-status! resp 405)) (DELETE [req resp] (send-status! resp 405)) (HEAD [req resp] (send-status! resp 405)) (OPTIONS [req resp] (send-status! resp 405)) (TRACE [req resp] (send-status! resp 405))) Alas I can't simply extend-type since that modifies the type, instead of creating a new, modified type. And even then, methods in the extension map don't get called if the method exists directly on the type, i.e., no overriding. I'm sure my problem is simply vestigial OO thinking, but I'm not sure how to achieve the simplicity I want. The one route I tried that sort- of works is making a macro to create the types, rather than extending some extant implementation. The downside is I have to see which methods I'm being given and only provide "defaults" for the method names/arities that aren't. It might be sufficient if there was some facility for cloning another type and overriding certain methods, though I can foresee problems dealing with managing the field definitions between the original and the altered clone. -- 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