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

design of update-instance-for-redefined-class and bug in PCL

Subject: Design of update-instance-for-redefined-class and bug in PCL

In 8-28-88-notes.text it says

- the initialization protocol specified in 88-002R is now almost
  completely implemented.  The only difference is that the current
  implementation does not currently check the validity of initargs.
  So, no errors are signalled in improper initargs are supplied.

There are several points, though, that either don't work yet or are not
clearly specified.

1. In update-instance-for-redefined-class (chapter 2) the argument
for initargs says 'The initargs argument consists of alternating
initialization argument names and values.' This is not clear enough for me.
Does that mean that the implementor has to / is allowed to pass the new
classes default-initargs here? Or is it even meant for the user who can
in some arguments here? I think that default-initargs definitely should be
passed here. See the following example:

(defclass a () ())

(setq inst (*make-instance 'a))

(defclass a ()
  ((s3 :initarg :s3))
  (:default-initargs :s3 'default-s3))

(slot-value inst 's3)    ;(after the error that is mentioned in point 3,
                         ; see below)
                         ; --> unbound, because only the initforms of added
                         ; slots are evaluated 

2. The spec also says that update-inheritance-for-redefined-class calls
shared-initialize with "a list of names of the newly added slots", which
are used for deciding whether initforms will be evaluated. For Slots that
are already there but are unbound in an instance a newly added initform
won't be evaluated.

(defclass a ()

(setq inst (*make-instance 'a))

(defclass a ()
  ((s1 :initform 's1)))

(slot-value inst 's1)    ; --> unbound 

I would expect, that the newly added initform of the transfered slot would
be evaluated if the slot was unbound in the instance at the time of class

Is this intented?

3. Now, the following is a bug in the PCL code.

- If you redefined a class slot update doesn't take place before you access
an *added* slot. So in the example below you can access s1 and even the
discarded slot s2 and get their old values.
Update-instance-for-redefined-class isn't executed before accessing s3.

- If you access the newly added slot s3 the first time you get a
slot-missing message. In spite of that the update takes place *after* the
error message  and results in a correct update.

(defmethod update-instance-for-redefined-class :around
   ((instance object) added-slots discarded-slots plist
     &rest initargs)
   (format t "instance ~S~%" instance)
   (format t "added-slots ~S~%" added-slots)
   (format t "discarded-slots ~S~%" discarded-slots)
   (format t "plist ~S~%" plist)
   (apply #'call-next-method 
       instance added-slots discarded-slots plist initargs)
   (Inspect (iwmc-class-static-slots instance)))

(defclass b ()
  ((s1 :initarg :s1 )
   (s2 :initarg :s2 )))

(setq inst (*make-instance 'b
               :s1 1 
               :s2 2 ))

(Inspect (iwmc-class-static-slots inst))

(defclass b ()

(Inspect (iwmc-class-static-slots inst))

(slot-value inst 's1) ;;; 1
(slot-value inst 's2) ;;; 2 - should be missing
(slot-value inst 's3) ;;; missing and update