On Dec 7, 11:23 am, ataggart <alex.tagg...@gmail.com> wrote:
> 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.

One idea:  (defdefault name options* specs*)

Similar to deftype except without any field definitions (a simplifying
restriction), thus can only operate on their args. With that I could
do:

(defdefault base-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)))

Then modify deftype to include "defaults" in the spec* set:

(deftype user-resource [user-id] base-resource
  (GET [req resp]
    (if-let [u (find-user user-id)]
      (send-entity! resp 200 u)
      (send-status! resp 404))))





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