[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Method Combination Proposal
- To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
- Subject: Re: Method Combination Proposal
- From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
- Date: Thu, 8 Jan 87 00:32 EST
- In-reply-to: <870107-172419-6152@Xerox>
Thanks for the comments. I hope to converge on this before the end of
the week.
Date: 7 Jan 87 17:24 PST
From: Gregor Kiczales <Gregor.pa@Xerox.COM>
The most significant comment I have about this is that in both of your
proposals, you mention functions like MAKE-METHOD-CALL which can only be
called from the body of a define-method-combination. (Moon says this
explicitly, Danny just implies it).
This may be overly restrictive. I think that all of these functions
should take an extra argument (tentatively named the
method-combination-identifier) which would allow them to be called by
sub-functions of the particular method combination. The exisitence of
this "method combination identifier" interacts with the arguments to the
method combination since this identifier would have to be passed in
somehow, and the first argument to the method combination is a natural
place.
The problem is that this makes the normal case more verbose. From a user
point of view, the need for this "method combination identifier", which
the user can't do anything with other than to pass right back to the
system, doesn't seem very well motivated. As an implementor I can see
why it's needed, but to the user it's just the system sticking its
dirty laundry in his face. See below.
It may be worth clarifying what this auxiliary information consists of.
In Flavors, it is the arguments that the generic function will pass to
the effective-method; more precisely, it is the lambda-list of the
effective-method (called the combined-method in Flavors). This might be
the same as, or derived from, the lambda-list of the generic function,
but in various special cases it can be something else. The important
point is that this information is needed to fill in the arguments to
be passed to the method by the form returned by make-method-call.
That's what it is in the 3600 implementation of Flavors. I don't think
it is wise to constrain it to be exactly this in all implementations.
So I could write
(define-method-combination mine (generic-function id)
((methods (*)))
(grovel-my-method-combination generic-function id methods))
(defun grovel-my-method-combination (generic-function id methods)
..
(make-method-call id methods :operator 'foo)
..)
What I had in mind was
(define-method-combination mine ()
((methods (*)))
(grovel-my-method-combination #'make-method-call methods))
(defun grovel-my-method-combination (make-method-call methods)
..
(funcall #'make-method-call methods :operator 'foo)
..)
which makes the auxiliary-function case more verbose, but keeps the
simple case simple. How does this strike you?
There were three other possible ways to deal with it that I didn't
like as well when thinking about this last year, but perhaps you
would like them better. All of them allow make-method-call to
be a globally-defined function, rather than a FLET function; the
advantages of this are that the user doesn't have to pass a closure
to the auxiliary function, and it becomes easier to bypass the
define-method-combination level and go directly to the meta-object
level, directly defining the method that define-method-combination
would expand into.
One is to pass any auxiliary information in special variables. This
is how it is currently done in Flavors.
The second is to pass any auxiliary information in the method objects.
It's likely that the generic function suffices and any other auxiliary
information can be found in slots of the generic function.
(See next issue.)
Finally, there is the approach of saying that it's a bad idea for
make-method-call to depend on any auxiliary information. Instead, it
should produce a form that just encodes its arguments in some suitable
fashion. The caller of the method-combination function has to further
process the returned form to make it into real executable code, by
putting in the actual argument forms whose values are to be passed to
the methods. I see three ways to do this; enclosing it in a LAMBDA or a
LET that binds variables whose names are known to MAKE-METHOD-CALL;
enclosing it in a MACROLET that defines a macro whose name is known to
MAKE-METHOD-CALL; or code-walking. Flavors experience (we used to do it
this way) shows that this is slower (at compile time) if you have to do
this extra level of macro expansion, but I don't think it's really such
a big deal. I'm almost convinced now that this is the right approach.
In addition to MAKE-METHOD-CALL, there is WARN (or METHOD-COMBINATION-ERROR),
which also requires auxiliary information in some form. Removing this
auxiliary information seems more difficult; I don't see an analogy to
the "bad idea" approach above. Any ideas about that?
In any case, I agree that the issue of auxiliary functions called
by method-combination functions needs to be addressed one way or
another in the document; either by showing how it's done, or by
asserting that it isn't allowed.
---------------
In addition, I think the body of the method combination should have
access to the generic function in question. It can't get it from the
methods since methods can be on more than one generic function.
I don't think that has been agreed to. It seems to be simpler to allow
sharing of method-functions, but not sharing of method-objects.
I agree that there should be a way for the body of define-method-combination
to access the generic function. We have that in Flavors, but it was
removed in the evolution of the CLOS proposal. It can be put back.
---------------
PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT. I don't see that this is an
appropriate mechanism for dealing with this optimization. It may just
be the name which is upsetting me, I am not sure yet.
The other way to deal with this is to make it a keyword argument to
make-method-call, which defaults to (eq operator 'progn). I would be
happy with that; in fact I think it's what I proposed originally, but when
we discussed this in Menlo Park, the change to PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT
was made (I forget who proposed it and what the arguments were).
Note that the simple form of DEFINE-METHOD-COMBINATION would need this
keyword argument too.
---------------
:qualifier-set vs. * in pattern-language etc.
Moon's most recent message shows how defmethod can check the legality of
the qualifiers just by calling the method-combination and seeing if it
warns or errors. This is probably good enough, but it should be noted
that it lacks the kind of precision of error message which Danny's
:qualifier-set proposal had. On the other hand, the kind of tool which
could make use of that precision of error message definitely comes under
the environment category.
So I guess just using the template language will be good enough.
OK
---------------
I also think the analogy between define-method-combination and defmacro
is useful, it would probably be worth including this analogy in the
spec.
OK