[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
- To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
- Subject: Re: Reinitialization
- From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
- Date: Wed, 20 Apr 88 23:51 EDT
- In-reply-to: <880413-111606-16288@Xerox>
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
update-instance-with-new-class previous current
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
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
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?
(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?
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?