How to deal with lists of objects?

Q&A's, tips, howto's
Post Reply
oofoe
Posts: 60
Joined: Wed Sep 28, 2005 7:13 pm
Contact:

How to deal with lists of objects?

Post by oofoe »

Hello!

I am trying to set up a little simulation project, but I am running into some problems with FOOPS and pass by value...

I have a Plane class, which considers the engine RPM and the altitude of the airplane:

Code: Select all

(new Class 'Plane)

(define (Plane:Plane rpm alt)
	(list 'Plane rpm alt))
Now, I might have methods that change the internal state of a particular instance of the Plane object. Here is one that firewalls the engine (goes to full throttle for a climb):

Code: Select all

(define (Plane:firewall)
	(setf (self 1) 2700))
This seems to work well enough for a single named instance of Plane:

Code: Select all

(setq aplane (Plane 1900 2000))
(println "Original: " aplane)
(:firewall aplane)
(println "Modified: " aplane)
Which produces:

Code: Select all

Original: (Plane 1900 2000)
Modified: (Plane 2700 2000)
However, if I try to create a list of many airplanes:

Code: Select all

(setq 
	planes (list 
		(Plane 2700 0)
		(Plane 2100 1250)
		(Plane 1500 900)))

(println "Original: " planes)
(dolist (p planes) (:firewall p))
(println "Modified: " planes)
This is what happens:

Code: Select all

Original: ((Plane 2700 0) (Plane 2100 1250) (Plane 1500 900))
Modified: ((Plane 2700 0) (Plane 2100 1250) (Plane 1500 900))
As you can see, nothing is changed. Upon further investigation (printing "p" after the :firewall call) I see that the intermediate object p is changed, but not stored to the list "planes". I assume that this is happening because as dolist iterates through planes, each Plane object is copied to p.

What is the best way to handle updating an object in a list of objects like this?

Also, for what it's worth, I have considered modifying :firewall to return self so I can do this:

Code: Select all

(dotimes (i (length planes))
	(setf (planes i) (:firewall (planes i))))
But I hope you can tell me there's a better way to handle it!

Thanks!
Testing can show the presence of bugs, but not their absence.

hugh.jf.chen
Posts: 7
Joined: Sun Aug 11, 2013 3:50 pm

Re: How to deal with lists of objects?

Post by hugh.jf.chen »

You need to modify the firewall function to return a new complete object with the modified value, and then set the original object to the returned new object.

Code: Select all

  
(define (Plane:firewall)
  (list Plane 2700 (self 2)))
Then,

Code: Select all

(set 'planes (map (curry : firewall) planes))
You will get:

Code: Select all

> planes
((Plane 2700 0) (Plane 2700 1250) (Plane 2700 900))

oofoe
Posts: 60
Joined: Wed Sep 28, 2005 7:13 pm
Contact:

Re: How to deal with lists of objects?

Post by oofoe »

OK, that's basically what I was suggesting in the last para, except that my modification looked like this:

Code: Select all

(define (Plane:firewall)
	(setf (self 1) 2700) (self))
It doesn't seem very efficient to have to replace the entire data structure each time I want to do an update. OOP may not be a good fit for this in NewLISP.

The approach I'm using is typical in other languages for dealing with particle simulations and the like. Maybe I should just use a list of lists and a double setf? However, the idea of OOP-style behaviour is very attractive.

Thanks for looking at it!
Testing can show the presence of bugs, but not their absence.

m i c h a e l
Posts: 394
Joined: Wed Apr 26, 2006 3:37 am
Location: Oregon, USA
Contact:

Re: How to deal with lists of objects?

Post by m i c h a e l »

When a method does not return a specific value, I usually return self. This was (is?) considered good practice when programming in Smalltalk. It allows you to chain method calls together. As to how inefficient it is, well, Lutz will have to be the one to address that.

m i c h a e l

Lutz
Posts: 5279
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Re: How to deal with lists of objects?

Post by Lutz »

Use time function to find out what is more efficient. Style wise I could live with both.

Post Reply