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

Reinitialization



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
	     defaulted-initargs)
      instance)))

(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)
				      initializer
                                      added-slots
                                      discarded-slots
                                      property-list)
  (funcall initializer instance))

(defmethod class-changed ((previous standard-object)
                          (current standard-object)
                          initializer)
  (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)
  (generic-labels
   ((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)
  (with-added-methods
   (initializer (instance &rest initargs)
    (:generic-function initializer)
    (:method ((instance my-class) &rest initargs) ...))
   (apply #'call-next-method instance initializer initargs)))]

			-rpg-