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