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

Re: Reinitialization



This message comments on the proposed revamping of the ch1 object
creation protocol in support of ch3.

    Date: 13 Apr 88 11:15 PDT
    From: Danny Bobrow <Bobrow.pa@Xerox.COM>

    The four updating functions are:

    initialize-new-instance instance &rest initialization-arguments
    reinitialize-instance instance &rest initialization-arguments
    update-instance-structure instance added-slots discarded-slots property-list
	 &rest initialization-arguments
    update-instance-with-new-class previous current 
       &rest initialization-arguments

This suggests renaming update-instance-structure to
update-instance-with-redefined-class.  With that change all five
names look consistent and fairly clear as to their meanings.

    These all call:

    initialize-instance instance slots-for-initform 
       &rest initialization-arguments

    The value of slots-for-initform can be a list of slot-names (possibly nil) or T,
    which is equivalent to specifying all slots of the instance.  For each slot on
    the list, if it is uninitialized, and it has an initfunction, it is initialized
    with the value of applying the initfunction to NIL. 

    What value does each of each of the updating functions pass to
    initialize-intance for this argument. 

    The call from initialize-new-instance passes T of course.
    The call from reinitialize-instance  passes NIL
    The call from update-instance-structure passes added-slots
    The call from update-instance-with-new-class passes new-slots

    Gregor and I previously argued that reinitialize-instance should try to
    reinitialize all the slots that were unititialized.  We claimed that this would
    allow a specialized reinitialization method to call slot-makunbound on just
    those slots wanted reinitialized.  However, achieving this is still easy.  The
    specialized method still makes these slots unbound, and passes along the list of
    slots that have been made unbound to initialize-instance.


    All four pass the initialization-arguments to initialize-instance.

    The call to update-instance-structure from the system of course passes NIL as
    the initialization-arguments.  So does the call to
    update-instance-with-new-class.  However, an :around method on either of these
    latter can compute some interesting initialization-arguments and do a
    call-next-method.

    As an example of the use, consider the following around method for
    update-instance-structure for point the above example:

    (defmethod update-instance-structure :around ((p point) ... 
	;;push :x and :y on the initarg list and call-next-method
    )

That only works if you change your method

  (defmethod initialize-instance :after ((p point)) &key :x :y)
     ;; if x and y are provided, use (setf point-x) (setf point-y)
     ;; to compute the appropriate values for rho and theta
  )

to be an initialize-new-instance method instead of an
initialize-instance method, and give it an ignored 2nd argument.  It
seems likely that if you made this error, many users will make it too,
especially since the two names are so similar.  I don't have any
suggestions I like for how to fix this.

Then the answers you propose to my seven issues are:

  (1) How much should be shared among the four updating functions?
The (new) initialize-instance generic function, thus as much or
as little as you want.

  (2) What should be shared among the four updating functions?  There are
  actually three different things:
  (a) the code to fill slots from initialization arguments
  (b) the code to fill slots from values of initialization forms
  (c) user-defined methods
All three, but under complete control through arguments.

  (3) We've discussed several clever/kludgey ways to tweak the shared code.
Do none of them.

  (4) A subtle semantic change to class-changed and update-instance-structure
Don't do it.

  (5) Do we really need four different updating functions?
Yes.

  (6) Why do the four updating functions have such inconsistent interfaces?
Because any alternative we could think of created more problems than
it solved, e.g. tempting the user to invoke methods that won't work.

  (7) What are good names for these five functions?
See above.

I'm happy with this.  Let's do it.

Let's see, what are the actual changes to chapters 1 and 2?

Rename initialize-instance to initialize-new-instance.

Rename update-instance-structure to update-instance-with-redefined-class
(if you like my proposed name) and change its arguments.

Rename class-changed to update-instance-with-new-class
and change its arguments.

Add new functions reinitialize-instance and initialize-instance.

Adjust the procedural description of make-instance accordingly.

Change all places that talk about filling slots to say it's done by
the default primary method for (the new) initialize-instance.

Add explanations of how the default primary methods for the
four updating functions call initialize-instance, where it now
says how they fill slots on their own.

check-initargs has to be called from four different places now,
as there are four updating functions that have initargs arguments.
I think the best way is to give check-initargs another argument,
which is a list of generic functions.  An initarg is acceptable if
it's a slot-filling initarg or if any of the generic functions in
the list accepts it.  make-instance would pass
(list #'allocate-instance #'initialize-instance #'initialize-new-instance).
reinitialize-instance would pass
(list #'reinitialize-instance #'initialize-new-instance).
The only problem with this is that each of these takes idiosyncratic
arguments, which check-initargs has to take into account when computing
the applicable methods.  Is there a better idea?

I think there is a little more technical fleshing out to be done before
this is reduced to purely editorial work, but it looks plausible.

Do any of the other committee members have an opinion on this?  Are we
going overboard on generality, or is this a good change that makes the
language more consistent and hence easier to understand?