On Mon Mar 14 19:54 2011, stu wrote: > The problem I have is with the myshapes.picture/draw function. As a > Clojure newb I keep wanting to think of this like a polymorphic > function in the O-O world that relies on each sequence member having a > draw function. > > What's the idiomatic way of handling a situation like this in > Clojure? Do I need to use richer data structures than vectors and > structs for the shapes so they carry some kind of type information? I > can see how a draw multi-method would work if the individual shapes > could be distinguished, or am I going about this the wrong way?
I believe there are two approaches to doing this in Clojure: 1. Multimethods: http://clojure.org/multimethods 2. Protocols: http://clojure.org/Protocols Of the two, as of Clojure 1.2, protocols are the preferred way of doing things. They handle the simplest and most common case of polymorphism: by type. You can define a set of functions for your shapes: (defprotocol Shape (draw [shape]) (rotate [shape angle]) …) Then you can convert your structs into records. So, instead of something like: (defstruct triangle :side1 :side2 :side3) You now have: (defrecord Triangle [side1 side2 side3]) You can implement your protocol inside of the defrecord itself or use extend or extend-type. An example of doing it inside of defrecord is: (defrecord Triange [side1 side2 side3] Shape (draw [this] ; assumes sides satisfy Shape protocol (draw side1) (draw side2) (draw side3)) (rotate [this] …) …) This method works fairly well, and you can even use it to define protocols for types you don't control, such as classes from a Java API. If you need some more complicated form of dispatch for polymorphism, there is the multimethod approach. Sincerely, Daniel Solano Gómez
pgpSND14zVdtO.pgp
Description: PGP signature