Hello, I wrote a function to replace
some item in a global variable, but it doesn't work.
Anybody know why? Here is the code:
(defun set->> (name slot val)
(let ((vallist (list (find-value name slot)))))
(rplaca vallist val)))
What it should do is find the value of
some slot in *frames* and replace it with the value
given in (set->> nam slot val).
e.g.
CL-user: (>> 'erik 'favorite-tv-station)
canvas
CL-user: (set->> 'erik 'favorite-tv-station 'bbc)
(bbc)
But it is not replaced in the *frames*, because I
still get :
((PERSON NIL ((NUMBER-OF-LEGS 2) (FAVORITE-TV-STATION VTM) (AGE #))) (ERIK
(PERSON) ((FAVORITE-TV-STATION CANVAS) (BIRTHYEAR 1970))))
instead of:
((PERSON NIL ((NUMBER-OF-LEGS 2) (FAVORITE-TV-STATION VTM) (AGE #))) (ERIK
(PERSON) ((FAVORITE-TV-STATION BBC) (BIRTHYEAR 1970))))
Here is the rest of the code.
(defvar *frames* nil)
;;; Contructor
;;;
(defun defframe (name parents &rest slots)
(push (list name parents slots)
*frames*))
;;; Accessors
;;;
(defun getframe (name)
(assoc name *frames*))
(defun frame-parents (frame)
(cadr frame))
(defun frame-slots (frame)
(caddr frame))
(defun remove-frame(name)
(setq *frames* (delete name *frames* :key #'first)))
(defun >> (frame message &rest args)
(let ((method (find-value frame message)))
(cond ((demonp method)
(apply (coerce (second method) 'function)
(cons frame args)))
(t method))))
(defun demonp (method)
(and (listp method) (eql (car method) :demon)))
;;; Simple inheritance (each frame can only have 1 parent to inherit
;;; from)
(defun find-value (name message)
(let ((frame (getframe name)))
(if (not frame)
(error "Undefined frame ~A" name)
(let ((information (assoc message (frame-slots frame))))
(if information
(cadr information)
(let ((parents (frame-parents frame)))
(if (null parents)
(error "Undefined message ~A for frame ~A" message name)
(find-value (car parents) message))))))))
(defframe 'erik
'(person)
'(favorite-tv-station canvas)
'(birthyear 1970))
(defframe 'person
'()
'(number-of-legs 2)
'(favorite-tv-station vtm)
'(age
(:demon (lambda (x &optional y)
(- (if y y 2001) (>> x 'birthyear))))))
On Tue, 26 Jun 2001 12:40:20 +0200, Joerivdv wrote:
> Hello, I wrote a function to replace
> some item in a global variable, but it doesn't work.
> Anybody know why? Here is the code:
> (defun set->> (name slot val)
> (let ((vallist (list (find-value name slot)))))
> (rplaca vallist val)))
LIST wraps the value returned by FIND-VALUE up in a fresh cons cell.
You then replace the CAR of that cell (which is the value you just
found!) with VAL. A faster way to do the same thing would just be
(defun set->> (name slot val)
(list val))
Now why would you expect that to affect NAME and/or SLOT?
You know, it would probably help immensely if you stopped writing code
and just sat down with a good book for a couple of days -- you need to
have some idea what the various functions in the language *do* before
you can hope to use them effectively. There's no point deciding you
need to use GENSYM in a function if you don't know what you want to
use it for, or even what it does.
> But it is not replaced in the *frames*, because I
> still get :
> ((PERSON NIL ((NUMBER-OF-LEGS 2) (FAVORITE-TV-STATION VTM) (AGE #))) (ERIK
> (PERSON) ((FAVORITE-TV-STATION CANVAS) (BIRTHYEAR 1970))))
> instead of:
> ((PERSON NIL ((NUMBER-OF-LEGS 2) (FAVORITE-TV-STATION VTM) (AGE #))) (ERIK
> (PERSON) ((FAVORITE-TV-STATION BBC) (BIRTHYEAR 1970))))
If you can get at the cons cell representing the "slot" you want to
change (i.e., the (NUMBER-OF-LEGS 2) object), you can change its CADR.
But your FIND-VALUE function returns the value (what's in the CADR),
so if you use that you don't have any "place" to change.
[Be careful not to end up changing the value in some shared parent!]
> (defun >> (frame message &rest args)
> (let ((method (find-value frame message)))
> (cond ((demonp method)
> (apply (coerce (second method) 'function)
> (cons frame args)))
(apply (second method) frame args) will do.
> (defframe 'person
> '()
> '(number-of-legs 2)
> '(favorite-tv-station vtm)
> '(age
> (:demon (lambda (x &optional y)
> (- (if y y 2001) (>> x 'birthyear))))))
What are you going to do if someone does
(set->> 'erik 'age 42)
You'll replace the function, so he'll remain 42 forever, regardless of
the year.
--
When C++ is your hammer, everything looks like a thumb.
-- Steven Haflich
(setq reply-to
(concatenate 'string "Paul Foley " "<mycroft" '(··@) "actrix.gen.nz>"))
Thanks for the advice.
I wrote this instead and it works.
(defun set->> (name slot val)
(setq *frames* (subst val (find-value name slot) *frames*)))
If you change the value for ('erik 'age 42) then that will
probably be for some reason. One can always change it back.
J.
"Paul Foley" <·······@actrix.gen.nz> wrote in message
···················@mycroft.actrix.gen.nz...
> On Tue, 26 Jun 2001 12:40:20 +0200, Joerivdv wrote:
>
> > Hello, I wrote a function to replace
> > some item in a global variable, but it doesn't work.
> > Anybody know why? Here is the code:
>
> > (defun set->> (name slot val)
> > (let ((vallist (list (find-value name slot)))))
> > (rplaca vallist val)))
>
> LIST wraps the value returned by FIND-VALUE up in a fresh cons cell.
> You then replace the CAR of that cell (which is the value you just
> found!) with VAL. A faster way to do the same thing would just be
>
> (defun set->> (name slot val)
> (list val))
>
> Now why would you expect that to affect NAME and/or SLOT?
>
> You know, it would probably help immensely if you stopped writing code
> and just sat down with a good book for a couple of days -- you need to
> have some idea what the various functions in the language *do* before
> you can hope to use them effectively. There's no point deciding you
> need to use GENSYM in a function if you don't know what you want to
> use it for, or even what it does.
>
> > But it is not replaced in the *frames*, because I
> > still get :
>
> > ((PERSON NIL ((NUMBER-OF-LEGS 2) (FAVORITE-TV-STATION VTM) (AGE #)))
(ERIK
> > (PERSON) ((FAVORITE-TV-STATION CANVAS) (BIRTHYEAR 1970))))
>
> > instead of:
>
> > ((PERSON NIL ((NUMBER-OF-LEGS 2) (FAVORITE-TV-STATION VTM) (AGE #)))
(ERIK
> > (PERSON) ((FAVORITE-TV-STATION BBC) (BIRTHYEAR 1970))))
>
> If you can get at the cons cell representing the "slot" you want to
> change (i.e., the (NUMBER-OF-LEGS 2) object), you can change its CADR.
> But your FIND-VALUE function returns the value (what's in the CADR),
> so if you use that you don't have any "place" to change.
>
> [Be careful not to end up changing the value in some shared parent!]
>
> > (defun >> (frame message &rest args)
> > (let ((method (find-value frame message)))
> > (cond ((demonp method)
> > (apply (coerce (second method) 'function)
> > (cons frame args)))
>
> (apply (second method) frame args) will do.
>
> > (defframe 'person
> > '()
> > '(number-of-legs 2)
> > '(favorite-tv-station vtm)
> > '(age
> > (:demon (lambda (x &optional y)
> > (- (if y y 2001) (>> x 'birthyear))))))
>
> What are you going to do if someone does
>
> (set->> 'erik 'age 42)
>
> You'll replace the function, so he'll remain 42 forever, regardless of
> the year.
>
> --
> When C++ is your hammer, everything looks like a thumb.
> -- Steven Haflich
> (setq reply-to
> (concatenate 'string "Paul Foley " "<mycroft" '(··@) "actrix.gen.nz>"))