Accessing parent objects in CLOS

Discussion of Common Lisp
Post Reply
jsmcgd
Posts: 9
Joined: Sat Jun 28, 2008 4:43 am
Location: UK

Accessing parent objects in CLOS

Post by jsmcgd » Tue Jul 29, 2008 12:31 pm

I was wondering what is the best way to access the parent of an object.
Is there a way to access the parent through the child object?

For example, imagine a simple game where by if a ball is in a certain position
(eg the goal) a goal is scored and the score for that game is updated.
Imagine also that the score is dependent on the size of the ball.
So a ball of size 3 gives you 3 points.
A ball of size 8 gives you 8 points etc.

Each game object has a ball object.

Code: Select all


(defclass game ()
  (score        :initform 0 :accessor game-score)
  (game-ball    :initform (make-instance 'ball)))

(defclass ball ()
  (size :initform 1 :accessor ball-size))

(defmethod move-ball (ball x y)
  (if (ball-is-in-goal-p x y)
      <update-score>
      (move-ball-as-normal)))

It's the <update-score> part I'm having trouble with.

I realize there are various things I could do
like make the ball a global variable or make the move-ball method accept
a game object. However is there something equivalent to
ball.parent.score?

findinglisp
Posts: 447
Joined: Sat Jun 28, 2008 7:49 am
Location: Austin, TX
Contact:

Re: Accessing parent objects in CLOS

Post by findinglisp » Tue Jul 29, 2008 3:00 pm

jsmcgd wrote:I was wondering what is the best way to access the parent of an object.
Is there a way to access the parent through the child object?
There is no way to do this automatically. You need to give the child a reference to its parent when it's created. Then you can access the parent through the child just like you can access the child through the parent.
Cheers, Dave
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/

jsmcgd
Posts: 9
Joined: Sat Jun 28, 2008 4:43 am
Location: UK

Re: Accessing parent objects in CLOS

Post by jsmcgd » Tue Jul 29, 2008 4:38 pm

Cheers.

Is this the accepted way or should I ideally be changing my architecture so I don't run into this problem too often?

Perhaps I should get cracking on AMOP?

qbg
Posts: 64
Joined: Mon Jun 30, 2008 1:05 pm
Location: Minnesota

Re: Accessing parent objects in CLOS

Post by qbg » Tue Jul 29, 2008 5:52 pm

If there is only going to be one game object, you could use a global variable.

Also, in your move-ball method, I think it would be better to dispatch when the ball variable is a subtype of ball instead of T.

jsmcgd
Posts: 9
Joined: Sat Jun 28, 2008 4:43 am
Location: UK

Re: Accessing parent objects in CLOS

Post by jsmcgd » Wed Jul 30, 2008 3:36 am

If I do decide to make a reference to the game object in the ball object,
how would one do this? Without a concept like this like you would
have in Java *shudder* how would you pass a reference to a parent object
to a child object when you haven't finished instantiating the parent object?

Use a factory or something? Its beginning to seem a bit kludgesque.

Kompottkin
Posts: 94
Joined: Mon Jul 21, 2008 7:26 am
Location: München, Germany
Contact:

Re: Accessing parent objects in CLOS

Post by Kompottkin » Wed Jul 30, 2008 5:19 am

jsmcgd wrote:Without a concept like this like you would
have in Java ...
But there is such a concept:

Code: Select all

(defclass game ()
  ((score        :initform 0 :accessor game-score)
   (game-ball    :accessor game-ball)))

(defmethod initialize-instance :after ((game game) &rest args)
  (declare (ignore args))
  (with-slots (game-ball) game
    (setq game-ball (make-instance 'ball :game game)))
initialize-instance's first argument sure looks a lot like a this reference to me. Yes, :initform is convenient, but it works for a certain class of special cases only. For more general needs, there's nothing wrong about adding a method to initialize-instance, i.e. defining a constructor as you would in Java.

dlweinreb
Posts: 41
Joined: Tue Jul 01, 2008 5:11 am
Location: Lexington, MA
Contact:

Re: Accessing parent objects in CLOS

Post by dlweinreb » Mon Aug 04, 2008 4:39 pm

There isn't any built-in CLOS concept of "parent" or "child" in the
sense in which you mean it. If your model is that there are games and
balls, and there's a one-to-one relationship between them, you's model
that using slots. The game would have a slot set to the ball object,
and vice versa. Then move-ball would access its "game" slot, using an
:accessor (or :reader, or with-slots, whatever), to get its hands on
the game object.

Exolon
Posts: 49
Joined: Sat Jun 28, 2008 12:53 pm
Location: Ireland
Contact:

Re: Accessing parent objects in CLOS

Post by Exolon » Thu Aug 07, 2008 4:24 pm

jsmcgd wrote:I realize there are various things I could do
like make the ball a global variable or make the move-ball method accept
a game object. However is there something equivalent to
ball.parent.score?
This isn't really possible... when you say 'parent', I think you just mean 'client' - by using the ball, the game class is a client of the ball class. But remember that any number of different objects can share a reference to the same ball. So if there was such a thing as ball.clients, it would return a set of objects which refer to the ball. Which isn't very helpful, of course. :)
What's usually done (at least in Java, C++ and the like, since I don't have experience with CLOS yet) is for the game to either pass a reference to 'this' (which doesn't seem to exist in CLOS?) to the ball, or perhaps to register a callback function defined by the game class with the ball object that should be called on certain events.

Post Reply