How to set in object parameter list...

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

How to set in object parameter list...

Post by oofoe »

As I understand it, setf can not only set a variable, it can also set a "place", in this case, a position in a list. So I can create a simple class:

Code: Select all

(new class 'Node)

(setq n (Node "test" '(5 3)))
If want to inspect or change the Node's coordinates, I can do this:

Code: Select all

(println "location: " (n 2))
(setf (n 2) '(9 9))
(println "new location: " (n 2))
However, if I want to encapsulate the list access into the class, it doesn't work for setting:

Code: Select all

(define (Node:where) ((self) 2))
(println "location: " (:where n))
(setf (:where n) '(14 3))
(println "same old location: " (:where n))
Is there any way to do anything like the above without having to define a separate getter and setter?

Thanks!
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 set in object parameter list...

Post by m i c h a e l »

I cannot think of a way of doing this, other than defining an accessor:

Code: Select all

> (context (new Class 'Node))
Node
Node> (define (location lst) (if lst (setf (self 2) lst) (self 2)))
(lambda (lst) 
 (if lst 
  (setf (self 2) lst) 
  (self 2)))
Node> (context MAIN)
MAIN
> (setq n (Node "test" '(5 3)))
(Node "test" (5 3))
> (:location n)
(5 3)
> (:location n '(14 3))
(14 3)
> n
(Node "test" (14 3))
> _
If you do want to set and get without writing an accessor, you could do the following to make the intention more clear:

Code: Select all

> (context (new Class 'Node))
Node
Node> (constant 'name 1 'location 2)
2
Node> (context MAIN)
MAIN
> (setq n (Node "test" '(5 3)))
(Node "test" (5 3))
> (n Node:location)
'(5 3)
> (setf (n Node:location) '(14 3))
(14 3)
> n
(Node "test" (14 3))
> _
Personally, I prefer the former solution.

m i c h a e l

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

Re: How to set in object parameter list...

Post by oofoe »

Thanks for taking a look Micheal!

Here's my latest stab at it. Although it could be better, it's not bad. It allows me to only specify a property name once, for instance. The major disadvantage is that if I want to set a property to nil, this won't do it since it uses a nil value as an indicator that you want to get the stored value of the property.

Code: Select all

(define (property i value)  (if value (setf ((self) i) value))  ((self) i))

; h3. Node

(new Class 'Node)

(define (Node:title v)  (property 1 v))
(define (Node:where v)  (property 2 v))
(define (Node:colour v) (property 3 v))

; h2. Tests

(define (assert what pass)
  (println what "..." ('("FAILED" "OK") (if pass 1 0))))

(setq n (Node "Sample" '(9 4) "green" nil ""))

(assert "Title set" (= "Sample" (:title n)))
(:title n "Revised")
(assert "Title changed" (= "Revised" (:title n)))

(assert "Coordinates set" (= '(9 4) (:where n)))
(:where n '(44 99))
(assert "Coordinates changed" (= '(44 99) (:where n)))

(exit) ; Comment out for post-mortem debugging.
It would certainly be nice to hack a macro which would allow a friendlier property specification syntax, but so far this eludes me.
Testing can show the presence of bugs, but not their absence.

Locked