On Dec 11, 11:56 pm, ataggart <alex.tagg...@gmail.com> wrote:
> On Dec 11, 11:44 pm, ataggart <alex.tagg...@gmail.com> wrote:
>
>
>
>
>
> > On Dec 11, 4:14 pm, Jason Wolfe <jawo...@berkeley.edu> wrote:
>
> > > I've been trying out the new branch, and on the whole I like it a lot.
> > >  I know it'll take some time to learn how do things properly the "new"
> > > way, and I've figured out how to do most of the things I want to do
> > > thus far.  Thanks, Rich!
>
> > > One thing I haven't figured out how to do cleanly without inheritance
> > > is to specify "properties" of objects in a hierarchical domain in a
> > > clean, efficient way.  I'm sure I haven't fully wrapped my head around
> > > the new abstractions, so I'd love to hear about a clean way to solve
> > > this problem.
>
> > > A very simple example is: I have a protocol "A", and sub-protocols
> > > "A1" and "A2".  Every A is either an A1 or A2, but not both (and this
> > > split is closed, as far as I'm concerned).  Sometimes I want to deal
> > > with instances of A1 and A2 together, and so I put the methods shared
> > > between all "As" in protocol "A".  But, at some point I need to
> > > separate out the "A1"s from the "A2"s.  To do this, it seems like I
> > > have at least three options:
>
> > > 1.  Add an "is-A1" method to Protocol A.  The problem with this option
> > > is that every type that derives from A1 needs to manually write out
> > > this method returning "true", and vice-versa for implementers of A2.
> > > Users could eliminate this by "extending" their types with a mixin map
> > > to A, rather than implementing it directly in the deftype.  But, this
> > > sacrifices readability (IMO) as well as efficiency.
>
> > > 2.  use (satisfies? A1 x) to determine if x satisfies A1.  The main
> > > problem with this, at least currently, is that satisfies? seems to be
> > > really slow in the negative case.  I profiled my (non-trivial) program
> > > and half the runtime was going to reflection in satisfies?  Moreover,
> > > this solution is not as general.
>
> > > 3.  Use a multimethod.  This would work generally and be reasonably
> > > efficient, but I feel like I'd be cluttering up my interface by mixing
> > > up protocols and multimethods.  On the other hand, I guess
> > > multimethods are the main (only?) hierarchical construct built into
> > > Clojure, so maybe this is what's intended.
>
> > > So, which do people feel is preferred?  Or have I missed a better
> > > option?
>
> > > Thanks!
> > > Jason
>
> > If I understand Rich's reasoning, what you want runs antithetical to
> > the protocols design, namely it being explicitly non-hierarchical.
>
> > As such, you'd instead have 3 composable protocols, A, B, and C (where
> > B and C would correspond to the functions of A1 and A2, respectively):
>
> > (defprotocol A (a [x]))
> > (defprotocol B (b [x]))
> > (defprotocol C (c [x]))
>
> > And then the type would reify the appropriate protocols:
>
> > (deftype A1 [] A B
> >   (a [] (println "in A1.a"))
> >   (b [] (println "in A1.b")))
>
> > (deftype A2 [] A C
> >   (a [] (println "in A2.a"))
> >   (c [] (println "in A2.c")))
>
> I should also note that isa? can be used for differentiation:
>
> user=> (def my-a (A1))
> #'user/my-a
> user=> (isa? (type my-a) ::A1)
> true
> user=> (isa? (type my-a) ::A2)
> false

Oh, and it occurs to me that you could create an after-the-fact
hierarchical relationship:

user=> (derive ::A1 ::A)
nil
user=> (derive ::A2 ::A)
nil
user=> (isa? (type my-a) ::A)
true

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