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

Re: Method Combination Proposal

    Date: 6 Jan 87 02:44 PST
    From: Danny Bobrow <Bobrow.pa@Xerox.COM>

    Moon says:
        Looking back over the old discussion, the motivation for the
        find-methods scheme was stated to be simplicity, but in each
        version it gets more and more complicated.  I don't think it really
        achieves its goal.  Allow me to offer a few other criticisms,
        briefly:  The :qualifier-set option duplicates the information in
        the arguments to find-methods, with a different syntax, and with a
        different expressive power (unless one resorts to the escape to a
        predicate function).
    But it is the escape that I expect to use, say, for allowing one to
    specify for example, that a qualifier is a real (realp) where one uses
    the numeric value to order the methods.  Or to specify a qualifier is
    any single symbol used as a name.   

I had assumed this would be done in Lisp instead of a special embedded
language.  See example below.

        ; this duplicate information will be highly error-prone.  
    One answer is to add a new possible value, :explicit, for
    :qualifier-set.  In this case, all  explicit calls to find-method will
    be examined to determine allowable methods.

To me this seems even more complicated.

        The :qualifier-set syntax doesn't seem to allow a way
        to say anything about unqualified methods and doesn't seem to have
        the flexibility to deal with methods with more than one qualifier. 
        The examples are hard to understand since the :qualifier-set syntax
        used in the :and example is not the same as the syntax described
        earlier, and because the backquotes and commas are messed up.
    I would be willing to look further at the language for :qualifier-set.
    It was there to answer the stated needs for environment information, and
    I didn't give it enough thought.

I don't understand this reference to environment information.  I have
never proposed any special programming environment facilities here,
other than the :description thing to control printed representation.
You're probably referring to my insistence that macros that don't check
their arguments, but just ignore anything they don't recognize, are bad;
I think this is a language issue, not an environment issue.  Bringing that
general point to the specifics of define-method-combination, I feel it's
important for a method-combination function to complain if there are
applicable methods that it doesn't support, rather than just ignoring
them.  I'm not proposing that there be a warning at defmethod time, or
that a smart editor tell you when you enter the function; those things
might be useful, but they really are programming environment issues and
probably not appropriate for the object-oriented programming standard.
I'm just saying the method-combination function should complain at the
time it is called (which could be run-time, when the generic function
is called, but is likely to be earlier in most implementations).

If I was going to do those programming environment facilities, I would try
to do them by calling the method-combination function and seeing what
happens, rather than by adding a new syntax to be used in the
define-method-combination specifically to convey that information.  This
is similar to the suggestion that the best way to find out what methods
are actually called is to call the method-combination function and
analyze the Lisp form it returns, rather than adding a new syntax for it
to return a list of methods.

Implementing this would require the condition system (another proposed
CL extension), or some other way to get control when the
method-combination function calls WARN.  (Perhaps this is a good
argument for putting back the METHOD-COMBINATION-ERROR function, which
my recent proposal said was unnecessary?  But I still think it's better
to call it WARN and let the programming environment use FLET to make it
different from the regular WARN if it needs to.)

Here's an example (promised above), showing how I would write a method
combination function that requires the qualifiers to be positive integers
and uses the qualifiers to control the order:

(define-method-combination example-method-combination ()
        ((methods (*)))         ;all methods with exactly one qualifier
  (dolist (method methods)
    (unless (typep (first (method-qualifiers method)) '(integer 0 *))
      (warn "Qualifier ~S of method ~S is not a positive integer"
            (first (method-qualifiers method)) method)
      (setq methods (delete method methods))))
  (make-method-call (stable-sort methods #'<
                       :key #'(lambda (method)
                                (first (method-qualifiers method))))))

I hope this example clarifies what I'm talking about now.  All the
special processing is in Lisp, not in an embedded language.  Indeed,
this loses some declarative expressiveness, and I can't really claim
that the definition of the meaning of the method qualifiers is contained
entirely, or even mostly, in the second line of the definition.
However, I think it makes sense for the declarative form only to deal
with the easy cases, and leave the complicated cases to imperative Lisp
code.  The switchover seems to be natural enough.

If you ask why have the declarative form at all, all proposals seem to agree
(tacitly?) that simple pattern-matching against symbols is the most common
case and is too verbose to write in Common Lisp.

    Moon says:
        The first part defines the meaning of the method qualifiers,
        while the second part defines how the methods are glued together. 
        It's important that the definition of the method qualifiers is all
        in one place, and I think it's important not to mix it up with
        other stuff.

    The question is whether it is there at point of use.  Why isn't it
    better to separate out environmental and programmatic concerns? 
I hope the above makes this question moot.

        A survey of Symbolics object-oriented code shows that the form
        of standard method combination with the primary methods in
        most-specific-last order is not needed, so the standard method
        combination does not need to take any arguments (another
        simplification relative to my earlier proposals).  The same survey
        showed that most-specific-last order is quite useful with some
        kinds of method combination that invoke all the methods (rather
        than shadowing), specifically progn, list, append, and, and or
        (this list is in decreasing order of popularity).  The survey also
        uncovered a user-defined method combination type that takes &key
        arguments, hence my proposal still includes arguments in the

    You do not show this one example, and I strongly prefer not having
    arguments for this form.  

The details of the example really aren't relevant or interesting.  I was
only interested in the fact that someone found &key arguments useful here.
What are your arguments against parameterizing method-combination schemas?

        A list of method-group specifiers follows. 

    I assume by this you mean the item noted by:
      ({(variable {qualifier-pattern}+ {keyword argument}*)}*)

Yes.  My English needs some cleaning up and clarification.

    Are the qualifier-patterns all lists or NIL, and hence distinguished
    from the keywords?

Possibly-empty lists or asterisks; this was in my message.

    The :ORDER keyword seems weak at best.

Agreed; the message said it was only a convenience and relegated it to
the "advanced facilities" section, for things that could be excluded if
we wanted a lean proposal rather than a comprehensive one.

    I don't see any way to specify to the environment that any single symbol
    would be an appropriate qualifier, or that a realp was OK.  

I hope the above example and discussion clarified this.

        Declarations at the head of the body are positioned directly
        inside of bindings created by the lambda-list, and outside of the
        bindings of the method-group variables.

    I don't understand this.  What does the declaration effect -- the
    computation of the effective method form, or the compilation of that
    form itself.

The former, same as in DEFMACRO.

        If a doc-string is present, it documents the method-combination
    Is this how we are going to do documentation.  Must we always provide
    such strings?  Didn't someone else complain about this.

I've not a fan of doc-strings, but I think it's much more important to be
consistent with the rest of Common Lisp than to make diddly improvements
here.  To my way of thinking, the syntax of DEFINE-METHOD-COMBINATION is
similar to the syntax of DEFMACRO and DEFSETF.  By the way, Flavors'
DEFINE-METHOD-COMBINATION doesn't allow doc-strings.

    If I had to rank my objections, my strongest one is against the lambda

I'd like to understand why.

    Next is the restrictive nature of the qualifier language (I think the
    escape to a predicate is crucial).

I hope this is clarified now (read my next paragraph first).  If not, we
need to keep discussing it.

    Finally, is the imposition of the idiom of putting the selection of
    methods up front.  I could live with this if the selection language (or
    at least the test for qualifiers) could be made stronger.  How about
    making that form be
    (variable find-method-filter &key :description :order)?

I feel like I might have missed the point of this suggestion.  Are you
saying that in place of the qualifier patterns one could put the name of a
predicate, in cases where the simple pattern match language wasn't strong
enough?  That seems like a good idea.  If you're suggesting adding a
hairier pattern match language, I don't go for that.

To make sure we understand each other, I'll rewrite the earlier example in
these terms:

(define-method-combination example-method-combination ()
        ((methods positive-integer-qualifier-p))
  (make-method-call (stable-sort methods #'<
                       :key #'(lambda (method)
                                (first (method-qualifiers method))))))

(defun positive-integer-qualifier-p (method-qualifiers)
  (and (= (list-length method-qualifiers) 1)
       (typep (first method-qualifiers) '(integer 0 *))))

Thus the syntax of the third subform of define-method-combination
would be extended to
      ({ (variable {qualifier-pattern}+ {keyword argument}*)
        | (variable predicate-symbol {keyword argument}*) }*)

    Somehow MAKE-METHOD-FROM-FORM got lost.  Isn't it needed in
    method-combination standard around the multiple-value-prog2 form?
    around is a list of methods, and the multiple-value-prog2 form is not.

My message said that MAKE-METHOD-FROM-FORM isn't needed.  Instead
MAKE-METHOD-CALL is generalized to accept forms as well as methods.

By the way, I find the analogies between DEFINE-METHOD-COMBINATION and
DEFMACRO useful in several ways.  Would it be a good idea to use that
analogy in the documentation?