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


At our last meeting, there was some sentiment for making the behavior of
add-named-class, ensure-generic-function and add-named-method more
uniform.  This message attempts to address those issues.

I have spent some time thinking about this, and I still feel that while
add-named-class and ensure-generic-function are similar, add-named-method
is different.  

One way to see this is to think about the defining forms which these
functions are the analog of.  add-named-class is the analog of defclass;
ensure-generic-function is the analog of defgeneric; add-named-method is
the analog of defmethod.

defclass and defgeneric each provide a way to specify the class of the
metaobject created.  One could imagine wanting to specialize the code
that created and installed that metaobject based on its class.  As an
example, one could imagine wanting to have special code for creating a
installing instances of a particular metaclass, say my-standard-class.

One way to provide this kind of functionality is to have add-named-class
and ensure-generic-functions each be generic-functions which specialize
on their first argument.  The first argument is the prototype instance
of the class of metaobject being created.  This leads us to define these
generic functions as:

(defmethod add-named-class ((proto standard-class)
                            &key name
  ;; This method implements the behavior specified for defclass
  ;; with (:metaclass standard-class).

(defmethod ensure-generic-function ((proto standard-generic-function)
                                    &key name
                                         (rest of options from pg 2-49)
  ;; This method implements the behavior specified for defgeneric
  ;; with (:generic-function-class standard-class).

On the other hand, defmethod provides no mechanism for controlling the
class of the generic function or the method it creates.  For this reason
it doesn't make sense for add-named-method to have that ability.
On the other hand, it is possible to make add-named-method a little more
uniform by having it take keyword arguments which get passed on to the
make-instance of the method.

(defun add-named-method (generic-function-name &rest keys
					       &key qualifiers
  (let* ((gf (ensure-generic-function 
               (class-prototype (class-named 'standard-generic-function))
	       :name generic-function-name))
         (new-method (apply #'make-instance
			    (generic-function-method-class gf)
         (old-method (get-method gf qualifiers specializers)))
    (when old-method (remove-method gf old-method))
    (add-method gf new-method)))

An alternate proposal would be to give the caller of add-named-method
more control over the arguments passed to ensure-generic-function.  My
feeling is that it isn't worth cluttering up add-named-method to do
that.  If someone wants more control over the arguments to
ensure-generic-function they can call it directly.