From what I read, the reasoning is that Clojure provides extremely
general multimethods where you have to define a dispatch function. On
the object side, there is metadata and you can do with it whatever you
want. But this seems to leave a gaping hole saying "fill me with an
object system". Is the goal for everyone to roll their own?
I'm against overusing objects, but there are things which quite
naturally map into the object-oriented paradigm. Let's take windowing
systems for example -- let's assume you have various kinds of windows,
each with its own unique attributes and attributes which are inherited
(e.g. a window-id attribute is common to all windows). I can't see how
you'd implement that in Clojure when you can't inherit structmap
attributes. How do I build my-special-window which is a kind of window
and also inherits window's window-id attribute? I know how to inherit
behavior, but there is behavior that requires data, and I have no idea
how to store and inherit that data. I looked at merge, but it seems you
can't merge structure basis objects.
Unfortunately, all discussion on Clojure polymorphism, multimethods and
objects that I could find seems to use overly simplified examples (it
really only shows that there are multimethods which can do multiple
dispatch on anything), and doesn't really help. Even Stuart Halloway's
beta "Programming Clojure" book has very simple examples that don't
inherit attributes, just use different type tags for the same
information.
--J.
> From what I read, the reasoning is that Clojure provides extremely
> general multimethods where you have to define a dispatch function. On
> the object side, there is metadata and you can do with it whatever you
> want. But this seems to leave a gaping hole saying "fill me with an
> object system". Is the goal for everyone to roll their own?
Hi,
Just curious, have you seen the "a la carte hierarchies" scheme that
Rich worked up last summer?
http://groups.google.com/group/clojure/browse_frm/thread/9cc9926de1bdb128?pli=1
Best,
Graham
(defn make-window [id]
{:tag ::window, :id id})
(defn make-color-window [id color]
(assoc (make-window id)
:tag ::color-window
:color color))
(derive ::color-window ::window)
(defmulti describe-window :tag)
(defmethod describe-window ::window [w]
(println "Window with ID" (:id w)))
(defmethod describe-window ::color-window [w]
(println (:color w) "Window with ID" (:id w)))
(let [w (make-color-window 24 "blue")]
(describe-window w))
;; => prints "blue window with ID 24"
On Jan 30, 3:16 pm, Stuart Sierra <the.stuart.sie...@gmail.com> wrote:Why is that the goal? I mean, the JVM provides a well defined, high
>
> I think the goal is to provide object-like capabilities without
> needing actual objects.
performance object oriented system. Clojure can already generate
classes - the main issue I see looking at the API is that it doesn't
look convenient to make "property bag" classes.
Let's focus on this part for now. As I mentioned, I do understand
multimethods and derive, and my post was not about them. In fact, I
noticed that multimethods and ad-hoc hierarchies are the only thing
people discuss, forgetting totally about attribute inheritance.
Phrased differently, I don't understand the utility of StructMaps. If
your example above is the preferred way to create objects that inherit
attributes from other objects, then this means inheritance is instance
(or prototype) based. I can extend the set of keys using assoc on a
particular instance.
But if that is so, what's the point of having StructMaps? You can use
defstruct to define your base object, but you can't use it to define
objects that extend the set of attributes (keys) -- you can only do that
to instances. So while I can use defstruct to define my base window
object and use struct-map afterwards, I can't define color-window this
way -- I always have to call make-color-window to create a color-window.
Let's follow the StructMap example from http://clojure.org/data_structures
-- I guess what I'm looking for is a way to do this (whatever the
actual syntax ends up being):
(defstruct desilu () (:tag ::desilu) :fred :ricky)
(defstruct extended-desilu (::desilu) (:tag ::extended-desilu) :lucy :ethel)
... instead of extending the set of attributes of a particular instance.
I guess I would be fine with delegating all responsibility to
constructor functions, but then I don't understand the point of having
StructMaps.
I have a nagging feeling that this amount of liberty will result in many
mutually incompatible object systems being created.
Another thing which I found very useful in CLOS were method
combinations, in particular the standard method combination with
:before, :after and :around method types. I am not sure if that is
implementable using the current Clojure multimethod system.
Any pointers or hints are very welcome.
--J.
This is interesting, thanks!
> Not too many people are doing heavy or fancy GUI related stuff (as far as I
> can tell) so I can understand why this hasn't come up often. I note that
> you work with weblocks so I can see where you're coming from and I'm glad
> you're bringing it up.
Yes, you get the same issue when writing a widget-based web framework. I
mean, I know functional programming is all the rage now, but there are
things which really are very well represented by objects and
inheritance, and GUI elements and web page widgets belong to that
category. Every widget has a dom-id and dom-class, for example, while
certain widgets also have other attributes.
> That said, I imagine if a decent, useful, and complete lightweight object
> system could be designed I'm sure it could get rolled into clojure-contrib
> without too much brouhaha.
That's what I was curious about -- I wanted to know whether this is the
desired outcome.
Also, before someone brings that up: I believe CLOS is overly
complex. I don't necessarily want all of CLOS+MOP in Clojure. Still, I
think there is a reasonable compromise to be found somewhere.
--J.
Am 31.01.2009 um 12:44 schrieb Jan Rychter:
> Phrased differently, I don't understand the utility of StructMaps.
At the moment struct-maps are an optimisation for the
case that you have a lot of maps of the same type.
struct-maps share there key information. No more, no less.
Sincerely
Meikel