There is no convenient way to inherit functionality. But there are a couple
other routes, perhaps one of these will appeal to you -

* Just use your rich Java library from Clojure, perhaps providing a high
performance integration the same way that Clojure does via RT.java and
inlining
* Use macros - see gvec.clj or defrecord.clj
* Write the shared code as helper functions that can deal with types via a
common access protocol

It's admittedly a real challenge taking a inheritance-centric design and
making it work in Clojure. But I consider it a fun and eye-opening one.

David

On Wed, Sep 28, 2011 at 6:40 AM, toxi <toxmeis...@gmail.com> wrote:

> Dear Clojurians,
>
> I picked up Clojure a few months ago and find it hugely fascinating.
> I've been working mainly with Java for the past few years and now
> trying to overcome the un-learning curve in regards to polymorphism
> and solving it with records & protocols instead.
>
> My aim is to port my library collection (http://toxiclibs.org) to
> Clojure. The core libs contain several type hierarchies of geometric
> entities (vectors, particles, shapes etc.) So I'm currently trying to
> find the best solution to the following (but would just like to get my
> head around this kind of problem in general):
>
> In Java I've got a Vec2D class which has a large amount of methods
> (80+) for vector algebra. I've also got a VerletParticle2D which
> subclasses Vec2D, and adds a bunch of new properties (and methods). In
> Java I only needed to implement the generic vector behaviours (adding,
> normalizing, scaling etc.) once in the Vec2D class and they become
> automatically available in VerletParticle2D. In Clojure I've tried to
> achieve this with protocols, but I can't see a way how to provide the
> same thing without having to re-implement the entire IVec2D protocol
> for both record types. The following works of course, but IMHO
> violates the DRY principle:
>
> (defprotocol IVec2D
>  (vadd [this v] "produces 2d vector sum of given vectors"))
>
> (defrecord Vec2D [^double x ^double y]
>  IVec2D
>  (vadd [this v] (Vec2D. (+ x (:x v)) (+ y (:y v)))))
>
> (defrecord VerletParticle2D
>  [^double x ^double y ^double mass behaviors constraints]
>  IVec2D
>  (vadd [this v]
>    (VerletParticle2D. (+ x (:x v)) (+ y (:y v)) mass behaviors
> constraints)))
>
> (def v (Vec2D. 23 42))
> (def p (VerletParticle2D. 11 22 3 [] []))
>
> (vadd v p) ; => #:user.Vec2D{:x 34.0, :y 64.0}
> (vadd p v) ; => #:user.VerletParticle2D{:x 34.0, :y 64.0, :mass
> 3.0, :behaviors [], :constraints []}
>
> The other option I thought of is using assoc instead of explicitly
> creating new instances and then injecting these implementations via
> the extend function:
>
> (def IVec2D-impl {
>  :vadd (fn [this v]
>    (assoc this :x (+ (:x this) (:x v)) :y (+ (:y this) (:y v))))
> })
>
> (defrecord Vec2D [^double x ^double y])
> (defrecord VerletParticle2D [^double x ^double y ^double mass
> behaviors constraints])
>
> (extend Vec2D IVec2D IVec2D-impl)
> (extend VerletParticle2D IVec2D IVec2D-impl)
>
> This is more concise, but also quite a lot slower due to assoc. Are
> there any other options I can try to realise this? Also, in the latter
> case, why does (parents Vec2D) doesn't list IVec2D, but in the former
> it does? How can I express a VerletParticle2D is a Vec2D? Using derive
> doesn't work with records...
>
> Super grateful for any answers/pointers/solutions!
>
> Thanks, K.
>
> --
> 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

Reply via email to