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


Something seems horrendously complicated about this whole affair.

There are 4 updaters:


In this message I use reinitialize-instance as the example.

These are called from parts unknown. They invoke a shared initializer
called shared-initialize. We want to be able write methods to change the
shared behavior, the gross behavior of the 4 updaters, and the behavior of
some of the behavior of what is otherwise shared initialization bahavior.
The modification in the last case depends only on which of the updaters
invokes the shared initialization rountine.

The point of my proposal was to have the shared initialization GF passed
in as an argument to the updaters so that one could write code that only
knew the calling protocol for the updater and which could locally modify
the initializer routine passed in. This way, even though shared-initialize
is always passed in, you can hack with it directly by writing a simple
method on reinitialize-instance.

Suppose reinitialize-instance were like this:

(defmethod reinitialize-instance ((instance standard-object) 
 				  initializer &rest initargs)
  <An incredibly hairy mess>
  (apply initializer instance initargs)
  <Weirder stuff than a human can imagine>)

Now if we want to alter the behavior of shared-initialize when
called by reinitialize-instance on some more specific class than
standard-object, we do the following:

(defmethod reinitialize-instance ((instance some-class) 
 				  initializer &rest initargs)
  (initializer (mess-with-generic-function initializer))
  (apply #'call-next-method instance initializer initargs)))

Notice we don't have to worry about the hairy mess and weird stuff in the
body of reinitialize-instance, *and* we've used an object-oriented programming
style to boot! This seems like the most common case to me.

Suppose you want to change shared-initialize to take an argument saying
why it was called. In this case I guess you can modify shared-initialize
to accept an special initargs pair encoding the caller and then modify the
4 updaters as above but to add the initargs pair.

Suppose we want to alter the behavior of shared-initialize any time
reinitialize-instance is called and there is no more specific class to
specialize reinitialize-instance on. Here it's trickier, but doable:

(let ((r-i #'reinitialize-instance))
  (initializer (mess-with-generic-function #'shared-initialize))
  (defmethod reinitialize-instance ((instance some-class) 
   				    initializer &rest initargs)
   (apply r-i instance initializer initargs))
  (defun fix-this-mess ()
   (setf (symbol-function 'reinitialize-instance) r-i))))

How would you do this with the flag scenario? I thought you would do this:

(let ((s-i #'shared-initialize))
 (defmethod shared-initialize ((instance standard-object)
                               &rest initargs)
  (if (member caller <my-silly-behvior-group>)
      (apply s-i instance caller initargs)))

Looks pretty familiar, eh?

Is there a better way? I think there is a simpler way:

(defmethod reinitialize-instance ((instance standard-object) 
 				  &rest initargs)
  (reinitializeds-shared-initialize instance initargs))

(defmethod reinitializeds-shared-initialize ((instance standard-object)
					      &rest initargs)
  (apply #'shared-initialize instance initargs))

(defmethod shared-initialize ((instance standard-object)
                              &rest initargs)

Now to alter the gross behavior, reinitialize-instance gets changed.  To
alter the shared behavior, shared-initialize gets changed.  To alter some
of the shared behavior, leaving the rest alone,
reinitializeds-shared-initialize (for example) gets changed. Note that this
makes people who don't use strange cases pay some performance penalty.

Now, this has to be too much hair for this problem. Maybe Kempf's
idea is right. Maybe we don't want to expose all of this for specialization.
If I had some idea what piece of code Danny and Gregor wanted to write, I
could think about this more clearly.