Re: mixins/multiple inheritance
The problem with the protocols approach is that it leads to an explosion in the number of explicitly defined records. His example was only with labels, but I can imagine he might have borders and any number of other decorations on the widgets, in which case he would need something like (defrecord Textfield ...) (defrecord LabelledTextfield ...) (defrecord BorderedTextfield ...) (defrecord LabelledAndBorderedTextfield ...) ; and so on for each combination of decorator and widget With the other approach he would only need a record for each widget and one for each decorator. -- 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
Re: mixins/multiple inheritance
I think the suggestions thus far are not ideal. Both protocols and multimethods provide a way to define a default case. The default case gives you opportunity to adopt a delegation / component based design. (defprotocol IFlightOrgan (flight-organ [this])) (defprotocol IFlight (can-fly? [this]) (fly [this] [this body])) (extend-type Object IFlight (can-fly? [this] (satisfies? IFlightOrgan this)) (fly ([this] (fly (flight-organ this) this)) ([this body] (fly (flight-organ this) body Now any type that provides a flight-organ can fly (note we even handle the self-sufficient case). How the flight organ is acquired is completely up to the provider - it could be a field or it could done via map lookup (if you need the type to be the aggregate of many components). This paper is really worth reading, Organizing Programs Without Classes http://cs.au.dk/~hosc/local/LaSC-4-3-pp223-242.pdf David On Sun, Feb 5, 2012 at 4:15 PM, Razvan Rotaru razvan.rot...@gmail.comwrote: Hi, I found some posts about this topic, but they did not clarify things in my head well enough, so I have to start my own... :) I'm basically craving for multiple inheritance or mixins, at least with my current way of thinking. I haven't really gone deep enough with multimethods or protocols, so I might be a little off track by looking for multiple inheritance. Let's take an example: I want to implement some gui widgets, so there's a main method render which draws the widget on the screen. I want to have two types: - Textfield - Datetimepicker Each can be mixed with the Label widget, so that we have: - LabelledTextfield - LabelledDatetimepicker So, two challenges occur: 1/ the render method for Label needs to call the render method for it's mixed widget (either Textfield or Datetimepicker) - let's assume that labels are rendered around the actual widget, so that we have a simple way to mix the implementations of render method 2/ the Label widget comes with its own data (the label text) For the second thing, I think it will work with defrecords, since the label can be a map entry which can be stored in the actual widget, even if it's not mixed with Label. I still want to point this out in case there are other ways of achieving this. How can I achieve 1? Are there alternatives for 2? Thanks for reading, Razvan -- 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 -- 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
Re: mixins/multiple inheritance
Hm, I wrote a reply yesterday figuring it would show up today (seeing as I accidentally double posted last time because it did not show up at once), but that reply seems to be lost. I see what you mean now, I think. Seeing as you will have to build your hierarchies yourself you might try something like the following: (defrecord Label [text]) (defrecord TextField [text]) (defmacro c-mix [orig o-args mixin m-args] `(with-meta (new ~orig ~o-args) {:mixin (new ~mixin ~m-args)})) ;; Extracting the mixin instance (defn mixin [o] (:mixin (meta o))) (defmulti render (fn [x] (or (class (:mixin (meta x))) (class x (defmethod render TextField [x] (:text x)) (defmethod render Label [x] (str (:text (mixin x)) : (render (with-meta x {} (def labelledtextfield (c-mix TextField Foo Label Name)) (def textfield (TextField. Foo)) (render textfield) ;= Foo (render labelledtextfield) ;= Name: Foo This will allow you to emulate dynamic mixin composition by using the c-mix macro which is like a constructor call that attaches an instance of the mixin object as meta data. I know you would like to avoid macros, but since it is not possible to instantiate an object from a function parameter I don't think you can avoid them entirely. Ad-hoc hierarchies using derive might also combine well with this solution, but then you would have to stay away from defrecord and define your own types I think. Regards, Matthias -- 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
Re: mixins/multiple inheritance
Is there a reason not to just use protocols for your mixins? (defprotocol Labelled whatever) (defprotocol Textfield whatever-else) (defprotocol Datetimepicker something) (defrecord Label Labelled whatever ...) (defrecord Textbox Textfield whatever-else ...) (defrecord LabelledTextbox Labelled whatever ... Textfield whatever-else ...) and so forth, and probably punt to external fns for anything that would otherwise get duplicated between Textbox and LabelledTextbox, or between Label and LabelledTextbox, and so forth. -- 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
Re: mixins/multiple inheritance
Cedric's is the approach I would take. Like he said, use private functions for the shared code. On Wed, Feb 8, 2012 at 8:49 PM, Cedric Greevey cgree...@gmail.com wrote: Is there a reason not to just use protocols for your mixins? (defprotocol Labelled whatever) (defprotocol Textfield whatever-else) (defprotocol Datetimepicker something) (defrecord Label Labelled whatever ...) (defrecord Textbox Textfield whatever-else ...) (defrecord LabelledTextbox Labelled whatever ... Textfield whatever-else ...) and so forth, and probably punt to external fns for anything that would otherwise get duplicated between Textbox and LabelledTextbox, or between Label and LabelledTextbox, and so forth. -- 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 -- 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
Re: mixins/multiple inheritance
It sounds like a use for the decorator pattern, or am I missing something? In case I am not I have given it a shot using records and protocols: (defrecord TextField [text]) (defrecord DatetimePicker [datetimes]) (defrecord Label [text widget]) (defprotocol Renderable (render [this])) (extend-protocol Renderable TextField (render [this] (str [ (:text this) ])) DatetimePicker (render [this] (apply str (:datetimes this))) Label (render [this] (str (:text this) : (render (:widget this) (comment (def textfield (TextField. Foo)) (def datetimepicker (DatetimePicker. [:yesterday :today :tomorrow])) (def labeledtextfield (Label. Name textfield)) (def labeleddatetimepicker (Label. Date datetimepicker)) (render textfield) ;= [Foo] (render datetimepicker) ;= :yesterday:today:tomorrow (render labeledtextfield) ;= Name: [Foo] (render labeleddatetimepicker) ;= Date: :yesterday:today:tomorrow ) 1/ is handled by the Renderable implementation of Label calling the Renderable implementation of whatever widget is decorated by the Label instance. 2/ is handled by having the label decorator as a record. Regards, Matthias On 5 Feb., 22:15, Razvan Rotaru razvan.rot...@gmail.com wrote: Hi, I found some posts about this topic, but they did not clarify things in my head well enough, so I have to start my own... :) I'm basically craving for multiple inheritance or mixins, at least with my current way of thinking. I haven't really gone deep enough with multimethods or protocols, so I might be a little off track by looking for multiple inheritance. Let's take an example: I want to implement some gui widgets, so there's a main method render which draws the widget on the screen. I want to have two types: - Textfield - Datetimepicker Each can be mixed with the Label widget, so that we have: - LabelledTextfield - LabelledDatetimepicker So, two challenges occur: 1/ the render method for Label needs to call the render method for it's mixed widget (either Textfield or Datetimepicker) - let's assume that labels are rendered around the actual widget, so that we have a simple way to mix the implementations of render method 2/ the Label widget comes with its own data (the label text) For the second thing, I think it will work with defrecords, since the label can be a map entry which can be stored in the actual widget, even if it's not mixed with Label. I still want to point this out in case there are other ways of achieving this. How can I achieve 1? Are there alternatives for 2? Thanks for reading, Razvan -- 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
Re: mixins/multiple inheritance
It sounds a little like the decorator pattern would do the trick for you in this case - am I missing something? In case I am not, I have given it a shot using records and protocols: (defrecord TextField [text]) (defrecord DatetimePicker [datetimes]) (defrecord Label [text widget]) (defprotocol Renderable (render [this])) (extend-protocol Renderable TextField (render [this] (str [ (:text this) ])) DatetimePicker (render [this] (apply str (:datetimes this))) Label (render [this] (str (:text this) : (render (:widget this) (comment (def textfield (TextField. Foo)) (def datetimepicker (DatetimePicker. [:yesterday :today :tomorrow])) (def labeledtextfield (Label. Name textfield)) (def labeleddatetimepicker (Label. Date datetimepicker)) (render textfield) ;= [Foo] (render datetimepicker) ;= :yesterday:today:tomorrow (render labeledtextfield) ;= Name: [Foo] (render labeleddatetimepicker) ;= Date: :yesterday:today:tomorrow ) 1/ is handled by the Renderable implementation for Label calling the Renderable implementation on whatever widget it decorates with a label. 2/ is handled by having the Label decorator widget as a record. Regards, Matthias On 5 Feb., 22:15, Razvan Rotaru razvan.rot...@gmail.com wrote: Hi, I found some posts about this topic, but they did not clarify things in my head well enough, so I have to start my own... :) I'm basically craving for multiple inheritance or mixins, at least with my current way of thinking. I haven't really gone deep enough with multimethods or protocols, so I might be a little off track by looking for multiple inheritance. Let's take an example: I want to implement some gui widgets, so there's a main method render which draws the widget on the screen. I want to have two types: - Textfield - Datetimepicker Each can be mixed with the Label widget, so that we have: - LabelledTextfield - LabelledDatetimepicker So, two challenges occur: 1/ the render method for Label needs to call the render method for it's mixed widget (either Textfield or Datetimepicker) - let's assume that labels are rendered around the actual widget, so that we have a simple way to mix the implementations of render method 2/ the Label widget comes with its own data (the label text) For the second thing, I think it will work with defrecords, since the label can be a map entry which can be stored in the actual widget, even if it's not mixed with Label. I still want to point this out in case there are other ways of achieving this. How can I achieve 1? Are there alternatives for 2? Thanks for reading, Razvan -- 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
Re: mixins/multiple inheritance
Thanks, This works, but there's a problem: the labeledtextfield is not a textfield anymore, it's a label. Therefore it does not behave like a textfield (which implements other protocols as well). I need multiple inheritance, in one way or another. I've been trying to find a way to implement with multimethods. For example, if label was a mixin, then it means I could do something like this: (def textfield (new TextField Foo) (def labeledtextfield (new (mix TextField Label) Name Foo)) (render textfield) ;= [Foo] (render labeledtextfield) ;= Name: [Foo] Oh, and I'd like to stay away from macros, if possible. :) Razvan On Feb 6, 12:20 pm, Matthias Diehn Ingesman matdi...@gmail.com wrote: It sounds a little like the decorator pattern would do the trick for you in this case - am I missing something? In case I am not, I have given it a shot using records and protocols: (defrecord TextField [text]) (defrecord DatetimePicker [datetimes]) (defrecord Label [text widget]) (defprotocol Renderable (render [this])) (extend-protocol Renderable TextField (render [this] (str [ (:text this) ])) DatetimePicker (render [this] (apply str (:datetimes this))) Label (render [this] (str (:text this) : (render (:widget this) (comment (def textfield (TextField. Foo)) (def datetimepicker (DatetimePicker. [:yesterday :today :tomorrow])) (def labeledtextfield (Label. Name textfield)) (def labeleddatetimepicker (Label. Date datetimepicker)) (render textfield) ;= [Foo] (render datetimepicker) ;= :yesterday:today:tomorrow (render labeledtextfield) ;= Name: [Foo] (render labeleddatetimepicker) ;= Date: :yesterday:today:tomorrow ) 1/ is handled by the Renderable implementation for Label calling the Renderable implementation on whatever widget it decorates with a label. 2/ is handled by having the Label decorator widget as a record. Regards, Matthias -- 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
mixins/multiple inheritance
Hi, I found some posts about this topic, but they did not clarify things in my head well enough, so I have to start my own... :) I'm basically craving for multiple inheritance or mixins, at least with my current way of thinking. I haven't really gone deep enough with multimethods or protocols, so I might be a little off track by looking for multiple inheritance. Let's take an example: I want to implement some gui widgets, so there's a main method render which draws the widget on the screen. I want to have two types: - Textfield - Datetimepicker Each can be mixed with the Label widget, so that we have: - LabelledTextfield - LabelledDatetimepicker So, two challenges occur: 1/ the render method for Label needs to call the render method for it's mixed widget (either Textfield or Datetimepicker) - let's assume that labels are rendered around the actual widget, so that we have a simple way to mix the implementations of render method 2/ the Label widget comes with its own data (the label text) For the second thing, I think it will work with defrecords, since the label can be a map entry which can be stored in the actual widget, even if it's not mixed with Label. I still want to point this out in case there are other ways of achieving this. How can I achieve 1? Are there alternatives for 2? Thanks for reading, Razvan -- 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