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

defgeneric :method option



This issue is still open: when a defgeneric is evaluated with a :method
option, and then evaluated again without the :method option, does the
method go away, reflecting the updated defgeneric, or does the method
stay around?

    Date: Tue, 19 Jan 88 11:45 EST
    From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>

    It wouldn't bother me a bit if we changed the language to require all
    implementations to remove methods that were created by a defgeneric, if
    the defgeneric were re-evaluated without the :method.  We already do this
    for accessor methods created by defclass.  We're now saying that the class
    remembers the specific method objects and removes them if they are still
    there; if they've already been replaced by a defmethod, it doesn't remove
    the method put there by the defmethod.

    What would bother me would be if we required all implementations to be
    stupid about this.

    So how about it?  Shall we change CLOS so that re-evaluating a defgeneric
    removes methods that were previously defined by :method, but no longer
    appear in the new defgeneric form?  I think we should.

    Date: Tue, 19 Jan 88 14:51 EST
    From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>

	Date: 19 Jan 88 09:37 PST
	From: Danny Bobrow <Bobrow.pa@Xerox.COM>

	I think that's a good idea.  Should we specify how defgeneric knows that a
	method was defined by :method.  We could use a predicate or we could make
	:method specified methods be a subclass of defgeneric-method.  This similar to
	how accessors methods are specified, and is what I reecommend.   

    We decided at our last meeting that each class has a slot in which it
    remembers a list of the defclass-defined methods.

    Date: 19 Jan 88 15:40 PST
    From: Danny Bobrow <Bobrow.pa@Xerox.COM>

	From: Moon
	I think defgeneric should handle its specially-defined methods
	in exactly the same way that defclass handles its.

    I agree.

	We decided at our last meeting that each class has a slot in
	which it remembers a list of the defclass-defined methods.  I'm not
	imagining this, am I?  I remember that idea winning out over giving
	each method a slot that says how it was defined or having
	defclass-defined methods be a special subclass.
    I don't remember this, but my memory and notes are not to be trusted.  Do you
    remember any of the arguments for this decision.  An argument against this is
    that it implies that remove-method, and add-method that overrides must both be
    cognizant of (side-effect) this list in this slot.

No, it doesn't imply that.  The class remembers the method objects that
it added to the generic function.  It's not required that if someone
else removes those method objects, they be removed from the class's
list.  Instead, when the class uses its list, it checks whether each
method is still known by the generic function.  This is what I remember
us concluding at our last meeting.

This works because Gregor argued down my idea that defmethod updates an
existing method object, instead of creating a new one that replaces any
previous one for the same generic function, specializers, and qualifiers.

    Date: 21 Jan 88  1428 PST
    From: Dick Gabriel <RPG@SAIL.Stanford.EDU>

	I think defgeneric should handle its specially-defined methods
	in exactly the same way that defclass handles its.

    I'm not sure what the specially-defined methods might be for a defgeneric.

All methods defined with the :method option.

    My reading of the specification states that if some method descriptions
    are supplied some methods are defined, but none of those are specially
    defined in the manner that they are using defclass - in the defclass case
    I suppose the specialness is tied up with the fact that they are
    implicitly defined, though at the behest of the :reader, :writer, or
    :accessor options. I notice no other methods mentioned.

    The model currently stated is clear - defgeneric is semantically equivalent
    to an ensure-generic-function and a series of defmethod's. 

It's true that the model currently stated is clear.  However, it has a
bad consequence, which is that evaluating a defgeneric form multiple
times has a different effect from evaluating the final version once.
None of CLOS's other defxxx forms have that property.  I'm proposing to
change the model to a different model, which is also clear:  defgeneric
is semantically equivalent to an ensure-generic-function, a series of
defmethod's whose values (method objects) are remembered, a series of
remove-method's of the remembered values from last time, and a setf to
remember the values for next time.  This model certainly involves more
parts than the previous model, but that's not surprising.  I don't
think there is anything unclear about it.

(progn
  (ensure-generic-function 'name :blah blah blah)
  (let ((methods (list (defmethod name blah blah blah)
		       (defmethod name blah blah blah)
		       ...))
	(generic (symbol-function 'name)))
    (dolist (method (generic-function-locally-defined-methods generic))
      (remove-method generic method))
    (setf (generic-function-locally-defined-methods generic) methods)
    generic))

							       I see no obvious
    parallel with defclass. With defclass, the ``specially-defined'' methods are
    so defined according to a strong convention that we have imposed - we would
    all be surprised to see people write simple defclass forms and then a
    series of defmethod's to build up the readers and writers. 

Not at all.  When I said exactly this, several months ago, someone (I think
it was Gregor) called me wedged and said that it was very important that the
user could just as well write reader and writer methods with defmethod and
get the same performance as when using the slot-option.  The only difference
is that defgeneric lets you define any kind of method, whereas defclass
only lets you define some very specific, stereotyped methods.

							       But the
    method-defining parts of defgeneric are for completeness only - we do
    not advocate that people write method definitions within defgeneric forms.
    If people do not like the fact that re-loading defgeneric forms doesn't
    do what they want, then they can re-write them as simpler defgeneric's
    and defmethod's, and they will be obeying classic object-oriented style
    all the more if they do. 

I really object to that.  What you're saying is that we're going to document
this :method feature of defgeneric, but then we're going to tell them that
it doesn't work very well, so they shouldn't use it.  In that case we would
be much better off removing it from the language entirely.

    So I am against treating these methods in a manner analogous to
    those defined by defclass.

Dick, I don't know if I have convinced you of anything in the above.
However, I have convinced myself of something.  I no longer think that
the current state of CLOS is acceptable.  To be an acceptable standard,
I now feel that we must either remove the :method feature from
defgeneric, or else we must make defgeneric remember the methods that it
defines and remove them when evaluated a second time.  Either of those
alternatives would be acceptable to me, although naturally I prefer the
second since it makes defgeneric more consistent with generic-flet.