[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Method Combination
- To: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
- Subject: Re: Method Combination
- From: Danny Bobrow <Bobrow.pa@Xerox.COM>
- Date: 28 Jan 87 13:40 PST
- Cc: Bobrow.pa@Xerox.COM, common-lisp-object-system@SAIL.STANFORD.EDU
- In-reply-to: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET's message of 27 Jan 87 17:39:46
- Sender: Bobrow.pa@Xerox.COM
Date: 27 Jan 87 17:39:46
From: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
I agree with the fact than one can define ones own
compute-effective-method. The issue has to do with modularity.
Compute-effective-method has to find the list of all the method
that can be called, find the method combination method, call it to
come up with the code for the effective method. We need to keep
those operations as independent as possible. If we supply the
information as an argument to the method combinator, the user
writing a method combination method does not have to worry about
how the information was obtained.
I agree that finding the list of all the methods that can be called,
finding the way to combine methods, and coming up with the code for the
combination ought to be kept separate. The following describes my view
of the meta-object protocol, and how these are kept separate.
The meta-object protocol for building the code for generic functions
consists of two parts. The top level is
(compute-discriminator-code generic-function)
which has as its responsibility building the code that implements the
effect of the described four step protocol for calling a method. Its
usual implementation caches all the possibly different effective methods
for the generic-function, and it produces code to decide which of these
effective methods to call for any set of arguments. It is this code
that is run when the generic-function is called.
The only information compute-discriminator-code can use must be
contained in the generic-function object. THERE IS NO OTHER PLACE TO
STORE INFORMATION.
As a standard part of the protocol for compute-discriminator-code (which
can be overwritten by a specialized method), compute-discriminator-code
computes the set of applicable-methods for distinguishable sets of
arguments, and for that set calls:
(compute-effective-method generic-function combination-type
applicable-methods)
The combination-type is taken from the generic-function to allow
discrimination on an individual (the combination type) to select a
specialized method. Other paramaterized information could have been
passed in as arguments, but since that information is not being used for
discrimination, it might as well be left in the generic function.
Different implementations of compute-effective-method will be
able to call the same method combinator even if they use different
ways to come up with the method combination method. It seems more
modular and more general than extracting the information in the
method.
If you want a subfunction that combines method-lists in the same way for
differently named method-combination types (say because the lists are
computed in different ways), then by all means define a subfunction.
That was the reason we wanted make-method-call to be callable any place
the generic-function object was accessible.
Date: Wed, 28 Jan 87 00:05 EST
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
I don't think the short form is vitally important, but until we
converge on all details of the long form it's difficult to tell how
much syntactic verboseness and error-proneness the short form will
save. I suggest that for right now a boldface note be added to the
document saying that the short form is still under discussion and
there is a good chance it will go away in a future revision.
I would rather do it the other way -- to make it easier to read the
document and to allow the need for a short form to emerge rather than
have it around by default. Only one form should appear in the document,
and prhaps we should have a footnote saying that we might consider a
short form if necessary.
I agree with Patrick's argument that storing parameters in the
generic function won't work.
I think I have answered Patrick above. If I have misunderstood the
thrust of the argument, please explain further.
I consider it important to design the lean standard so that
such extensions can be added smoothly and painlessly, without
making incompatible changes to the original standard. This means
that some design choices, which could go either way when considered
in isolation, need to go a certain way in order to leave room for
possible extensions. Is this agreeable to the other participants?
I agree with this in principle, and would want to see the argument in
any particular case.
This is the reason for the lambda-list. Having to say () now
is relatively painless, but adding a lambda-list in the future
would be difficult. In fact the lambda-list also turns out to be a
better way to provide access to the generic-function object than
any other I've thought of.
I've answered for the lack of need for the lambda-list above. The
lambda-list cannot just be (). In your examples, it was at least
(generic-function) or (generic-function order). This is not even the
complete lambda-list of compute-effective-method (it doesn't include
combination-type and applicable-methods).
I would be agreeable to removing the :order keyword if a lean
standard is paramount, although it seems to add only minimal
complexity and I've seen reversed order of method specificity used
quite a lot.
Most slightly shorter forms are used if they are available. But I
wouldn't cry a lot if this were put back.
I'm opposed to using optional arguments instead of keyword
arguments, because it makes extensibility much more awkward.
This is a case in which allowing for extensions seems to be the
paramount issue. Is it really musch easier to start with optionals and
then add keywords for extensions than to have all keywords. Not having
programmed with them very much, I can't speak from experience. I would
be happy to back off on this.
Using a special value for the :operator argument instead of a
:call-next-method argument would be okay with me, although I
suspect it will be difficult to document in a way that does not
cause confusion.
I think it will be less confusing for users to think of
:call-next-method as a special kind of operator. We seem to have no
real disagreement here. An argument for using the :call-next-method
instead of 'call-next-method (no colon) is to avoid people believing
that there is a function by that name, as there is for progn and and.
{method-combination-option} :=combination-keyword value
The list of method-combination options is optional, and is
distinguished from a form because it starts with a keyword.
We have this syntax for method-combination options in Flavors
and I think it is grotesque. I suggest not including this.
Can you say more about why you think it is grotesque. I find it easy to
spot and read.
The variable {\it generic-function\/} is available in
the body forms of the combination definition.
That's how we do it in Flavors (the variable name is slightly
different) and I think it is grotesque. It's usually better to let
the programmer choose her own names for variables. I suggest not
doing this, although I don't feel very strongly about it.
I think this is the simplest way to get access to the generic-function,
and if the programmer wants to use a name of her own, then she can
rebind it.
Question: How does make-method-call get access to the generic function.
I believed that it could assume access to that name in the lexical
scope. Or perhaps generic-function should be a dynamic variable, to
allow access for an error function.
(From Gregor) I like the new :around method-combination option.
I think
this will make it easier for people to deal with :around
methods. We might want to think about changing the "sense" of
this option, or changing the default, so that aroundification
happens by default.
(From Moon) I agree that once it's a yes/no option, it makes sense
to have
it turned on by default. The next logical step is to say that if
you want to turn it off, you should be operating at the meta-object
level. Do you ever feel like you're going around in circles? What
got us to :around methods in the first place was you guys' dislike
of Flavors whoppers, which cannot be turned off. (Obviously if
Flavors had meta-objects, whoppers could be turned off at the
meta-object level.)
Because around methods are still somewhat contentious (e.g. with
Fahlman) that I think :around should be explicit in the
define-method-combination code, and it should have to be turned on.
Standard method combination supports it without having to say something.
I understand the motivation for allowing a predicate
instead of the templates. I think that motivation should be
presented explicitly since without it, the predicate seems like
uneeded complexity.
I agree. Danny, could you write a paragraph about this? (Am I
remembering correctly that you invented the idea of putting the
predicate here?)
Yes I will. Yes I did.
We've found that it's often a good idea to provide a function
as an abstraction, even when all that function does is signal a
condition. The name of the condition can be the same as the name of
the function, so that there aren't any extra names to document.
This is what I had in mind here, rather than making a kludge to
cope with not having a standard condition system yet.
I suggest leaving this the way it is except for documenting the
rationale better.
I could go either way with this. If we have to document two kinds of
errors anyway, I guess it is as well to document functions.
I still don't like calling the default kind of method
combination standard. I would prefer if we called it default,
in fact, it might be better to call it daemon-with-around or
some other descriptive name.
I disagree. I really liked Danny's suggestion of calling it
standard. As you know, I think all the predefined objects that are
used by default if you don't make your own should be named
standard-xxx (standard-class, standard-method, etc.) I suggest
naming it either standard or standard-method-combination.
I still like "standard" since it is only used in a context that makes it
clear what it is the standard for.
One answer is for that library to be available, but not
necessary to be preloaded in all implementations. Then the
portable programmer can load it if it is not already loaded, but
doesn't have to reinvent it.
I suggest that the document should mention this issue but that
the name of and method combination in the example should still be
and.
I agree with both of these points. I think talking about standard
libraries here would be a good way of getting the point in the large,
without committing us to solve a problem.
My conclusion is that we should only have one define-method-combination
form in the document. The one still contentious issue between Moon's
and my ideas on this subject is the lambda-list. I hope this message
sheds more light on that issue. We should continue to try to reach
some consensus.
danny