[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

2 problems



   Posted-From: The MITRE Corp., Bedford, MA
   Date: Mon, 23 May 88 10:12:44 EDT
   From: bds@mitre-bedford.arpa

   We are running genera 7.2 on 3650's.  I've experienced the following 2
   problems:

   1) Suppose I have the following:

   (defvar *a*)
   (defvar *b*)

   (defun eq-test ()
     (let ((a '(a b c d))
	   (b '(a b c d)))
       (setq *a* a)
       (setq *b* b)))

   After running eq-test, it turns out that *a* and *b* are eq!
   This, by the way, occurs with arrays, strings, etc.  The only
   way to avoid this is to make liberal use of copy-* in these
   functions.

I can't find where in CLtL it says that this is permitted, but I
believe it is.  It may be one of the clarifications that the ANSI
Common Lisp committee has specified.

In general, the reason for two structures to not be EQ is so that you
can modify one without modifying the other.  However, I believe that
Common Lisp doesn't specify the behavior of modifying a structure
created as a result of evaluating/compiling a quoted constant; this
would actually result in a modification to the function itself in most
implementations.  Since you aren't permitted (portably) to modify such
structures, it's valid to make equal structures be eq.

The right way to write this function is:

(defun eq-test ()
  (let ((a (list 'a 'b 'c 'd))
	(b (list 'a 'b 'c 'd)))
    (setq *a* a)
    (setq *b* b)))


   2) Suppose I have a structure named rts which is stored as a
   named vector.  Given an instance of this structure, rts-1,
   if I then do (setq rts-2 (copy-rts rts-1)), I find that although
   every slot of rts-2 is eq to the corresponding slot in rts-1,
   rts-1 and rts-2 are not equal !  

EQUAL of structures is not defined.  Two structures are EQUAL only if
they are EQ.

   Moreover, given that the nominal-equipment-list slot of rts is a list
   of equipment structures, I find that

   (eq (rts-nominal-equipment-list rts-1)
       (rts-nominal-equipment-list rts-2))

   returns t, but when I do 

   (push t (rts-nominal-equipment-list rts-1))

   rts-1 is modified but rts-2 is not!

(push thing place) is essentially equivalent to

(setf place (cons thing place))

so your example is

(setf (rts-nominal-equipment-list rts-1)
      (cons t (rts-nominal-equipment-list rts-1)))

This only modifies rts-1, not rts-2.  Actually, after this, it is the
case that (eq (cdr (rts-nominal-equipment-list rts-1))
	      (rts-nominal-equipment-list rts-2))