From: Joerivdv
Subject: frame
Date: 
Message-ID: <3b38669d$0$93447$ba620e4c@news.skynet.be>
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))))))

From: Paul Foley
Subject: Re: frame
Date: 
Message-ID: <m24rt3l9v1.fsf@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>"))
From: Joerivdv
Subject: Re: frame
Date: 
Message-ID: <3b3882f7$0$93447$ba620e4c@news.skynet.be>
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>"))