On Dec 7, 11:23 am, ataggart <[email protected]> wrote:
> On Dec 7, 9:07 am, Laurent PETIT <[email protected]> wrote:
>
>
>
>
>
> > 2009/12/7 Hugo Duncan <[email protected]>
>
> > > On Mon, 07 Dec 2009 06:53:38 -0500, Rich Hickey <[email protected]>
> > > 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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en