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


I agree with Gregor's analysis and with the general outline
of his solution. However, I usually have bad reactions to
the use of flags to signify flow of control, so I would prefer
to have some other means of implementing the solution.

Here is a possibility, which has its own drawbacks, but which I
believe is better. Sample code:

(defmethod make-instance ((class standard-class) &rest initargs)
  (let ((defaulted-initargs (default-initargs class initargs)))
    (check-initargs class defaulted-initargs)
    (let ((instance (apply #'allocate-instance class defaulted-initargs)))
      (apply #'initialize-instance class #'shared-initialize

(defmethod initialize-instance ((instance standard-object) 
		                initializer &rest initargs)
  (apply initializer instance initargs))

(defmethod reinitialize-instance ((instance standard-object) 
 				  initializer &rest initargs)
  (apply initializer instance initargs))

(defmethod update-instance-structure ((instance standard-object)
  (funcall initializer instance))

(defmethod class-changed ((previous standard-object)
                          (current standard-object)
  (funcall initializer current))

(defmethod shared-initialize ((instance standard-object)
                              &rest initargs)
  .. initialize the slots from the initargs in the order ..
  .. specified in chapter 1                              ..
  .. for any slots which are still unbound, initialize   ..
  .. them from their initforms                           ..

Each of the update functions would take an extra argument, which
is the initializer function. The code that invokes the updaters would
pass in the current function binding for shared-initialize. If a user
wanted to alter the shared initialization behavior he would define
a method on shared-initialize, as in Gregor's scheme.

If he wanted to define radical new update behavior, he would define
methods on initialize-instance, reinitialize-instance,
update-instance-structure, or class-changed, as in Gregor's scheme.

Suppose he wanted to change the initialization behavior for, let's
say, reinitialize-instance. In Gregor's scheme he would write a method
on shared-initialize which discriminated on the identity of the second
argument. In my proposal he would write a method on
reinitialize-instance and supply a new initializer function:

(defmethod reinitialize-instance ((instance my-class) 
 				  initializer &rest initargs)
   ((shared-initialize ...))
   (apply #'call-next-method instance shared-initialize initargs)))

[Note that due to the 2 namespace problem I cannot use with-added-methods
to easily alter initializer. Maybe we should change with-added-methods
to add an option that says here is the generic function to use?

(defmethod reinitialize-instance ((instance my-class) 
 				  initializer &rest initargs)
   (initializer (instance &rest initargs)
    (:generic-function initializer)
    (:method ((instance my-class) &rest initargs) ...))
   (apply #'call-next-method instance initializer initargs)))]