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

method-lambda and apply-method-lambda



I've been thinking about this issue and here's my considered opinion.

    Date: Fri, 15 Jan 88 13:11 PST
    From: Gregor.pa@Xerox.COM

    A problem we have never quite resolved is how to abstract out the
    information about call-next-method (and slot optimization) that needs to
    be passed to method functions.  I have said on several occaisons that I
    would like for it to be possible to apply method functions to the
    'natural' arguments; I would also like it to be possible to construct
    method functions.  Moon has countered quite rightly that this makes it
    difficult to implement call-next-method.

    Briefly I propose that we introduce a constructs called method-lambda
    and method-apply.

I strongly agree with these goals.  I think we're still searching for the
right constructs to satisfy the goals.  I think Patrick is on the right
track, though.

    Date: Fri, 25 Mar 88  14:38:09 CST
    From: Patrick H Dussud <DUSSUD@Jenner.csc.ti.com>

    I don't think that method-lambda, as describe in 88-003 is good enough.  It
    captures the contract between a class of generic functions and a class of methods,
    so it should be metaclass driven.  You can imagine several contracts on a single
    implementation. 

    I propose the following:

    Make-method-function is a generic function.

    make-method-function GENERIC-FUNCTION QUALIFIERS SPECIALIZERS LAMBDA-FORM &optional MACROEXPAND-ENVIRONMENT

    The generic function make-method-function returns a function suitable for the
    function slot of a method. Its representation is implementation dependent.

I think the -only- assertions guaranteed about the value returned by
MAKE-METHOD-FUNCTION should be:

 - COMPILE works on it
 - the FUNCTION special form works on it
 - it and the result of compiling it are members of the type FUNCTION
 - APPLY-METHOD works on it and on the result of compiling it
 - it and the result of compiling it can be used as the :method-function
   when creating or reinitializing a method meta-object

A plausible implementation technique is for MAKE-METHOD-FUNCTION to return
a list whose car is LAMBDA and whose cdr is implementation-dependent.  Other
implementation techniques are also possible.

    apply-method METHOD NEXT-METHOD-LIST &rest ARGUMENTS [ generic function]

    apply-method  is discriminated on METHOD.

    METHOD is the method that needs to be invoked.
                                                                                
Using a method meta-object rather than a method-function is an interesting
change.  After thinking about it, I agree that this is right.  The meta object
encapsulates all the static information that might determine what calling
sequence to use (generic function, specializers, and qualifiers) while the other
arguments to APPLY-METHOD are all the dynamic information that can be needed
for calling a method.

    NEXT-METHOD-LIST is the list of all the methods that can be invoked by calling
    call-next-method.

There is an interesting question here whether this should be explicitly a list
of method objects, or should be abstracted as some implementation-dependent
object that represents that list.

    Date: Fri, 25 Mar 88 13:43:43 -0800
    From: kempf@Sun.COM

    Why, precisely, do you think there need be any difference between a method
    function and any other kind of function? I can understand this for
    a generic function, since a generic function has slots, but a method
    function has none. It seems to me that most of how a method function
    differs is covered by additions to its lexical environment, and that
    FUNCALL and APPLY should do.

    Date: Mon, 28 Mar 88  12:38:59 CST
    From: Patrick H Dussud <DUSSUD@Jenner.csc.ti.com>
     
    I agree that in structure, a method function is like any other function. However
    method functions are getting called with(in) an implementation dependent
    environment that must be abstracted from the user. This is the motivation for
    the encapsulation (method-lambda, apply-method-lambda) given in chapter 3. The
    point of my earlier message is that this encapsulation should be metaclass
    dependent. 

    The things that may be contained in the environment are(among others):
    Permutation vector(s), call-next-method list.

    This environment is distinct from the lexical environment of a closure.  That
    does not prevent some implementation to code it as if it were a lexical
    environment, but that's an implementation choice.

I agree with Patrick's response here.  It can be further clarified by understanding
the difference between static information (always the same for a given method) and
dynamic information.  Permutation vector(s) and call-next-method list are dynamic,
they depend on the (classes of the) arguments, thus they cannot be supplied by using
a lexical closure as the method-function.

    Date: Mon, 28 Mar 88 11:35 PST
    From: Gregor.pa@Xerox.COM

    Since, as you say, the method function captures the contract between a
    class of generic function and a class of method, I think this generic
    function should receive the prototype method as an argument as well.

Agreed.

    I am not sure that I want to have to pass the method to apply-method?
    If I am going to pass the method, why don't I also pass the generic
    function?

No, I think passing the method object is right (see my comment above).
However, you could convince me that apply-method should take all three
of the method-function, the method, and the generic-function.  One way to
convince me of this would be to show a case where one wants to call a
method-function that is not the current method-function of any method
(perhaps when tracing).

    Also, I am pretty sure we want to make compile work on these

Agreed.

    Perhaps the solution is
    to have the generic function you say, but specify in addition that the
    standard method returns (METHOD-LAMBDA (..) ...).

No, I think it's important to define the -behavior- of what
make-method-function returns, but to leave the -representation-
implementation-dependent.  I don't think it's a good idea to introduce
this new symbol that is like LAMBDA.  More about this directly below.

    Date: Mon, 4 Apr 88  07:16:49 CDT
    From: Patrick H Dussud <DUSSUD@Jenner.csc.ti.com>

         Date: Mon, 28 Mar 88 11:35 PST
         From: Gregor.pa@XEROX.COM
     
         The point is that in this case the `method function lambda' appears
         lexically in the source code.  That means that it can capture the
         lexical variable function.  It also means that it is compiled at
         compile-file time.
         I think both of these are important properties.

    I see your point, but the problem is that you can't decide at compile time what
    will be the implementation of the abstraction without knowing anything about the
    class of generic function, or the method.

Right.  I agree that the two properties Gregor proposes sound important,
but I believe that it is impossible to achieve those properties.  I think
that the attempt to achieve those properties is why we've been having
trouble converging here.  Giving up those properties will make the problem
much easier, and I don't think it means giving up anything that matters.

Another point I want to make is that both Gregor's and Patrick's versions
of advise-1-arg-method [I'll omit repeating the code here] don't work,
because they use FUNCALL on the result of METHOD-FUNCTION.  You have to
use APPLY-METHOD, not APPLY or FUNCALL.  I assume this was an accident,
not a proposal that FUNCALL should work on these functions.

    The problem with make-method-function being a function instead of a macro is
    that even if all of[ GENERIC-FUNCTION QUALIFIERS SPECIALIZERS ] were known at
    compile time and constant, we couldn't do the closure you had in mind. 
    If this is seen as a problem, we could make make-method-function be a macro
    that evaluates GENERIC-FUNCTION QUALIFIERS SPECIALIZERS at macroexpand time then
    calls the generic function

I don't think this is a good idea.  If users want to write macros whose expander
functions call make-method-function, they can do that.  In fact I think that
will be done often, and I approve of it.  make-method-function itself, as a
primitive, should remain a function, not be turned into a macro.  I don't think
it's useful to provide a built-in macro version of this, because I think any
macro that calls make-method-function is going to do other things as well.

    Note that your example does not work anyway. You call the original method
    function, but the continuation (a representation of the next-methods list) is
    lost in the process.

-Part- of what I was complaining about with use of FUNCALL.

    I am sure that we need something, like a local macro
    defined inside of the expanded method function, that allows someone to get at
    the continuation, and then pass it to apply-method-function. I'll have to think
    more about it.

Agreed.  See my comment above on whether the second argument to
APPLY-METHOD should be a list of method objects or something more
abstract.

Here's what I think we should do:

    MAKE-METHOD-FUNCTION proto-method generic-function qualifiers specializers
                         lambda-exp &OPTIONAL macroexpand-environment

and the return value's behavior is defined as I proposed above.
Note that the functions CALL-NEXT-METHOD, NEXT-METHOD-P, and
NEXT-METHOD-INFO [see below] have bindings in a scope that includes
all forms in lambda-exp.  *** Note that I am proposing a change here;
88-002 would make the scope include only the body of lambda-exp, but
Flavors users convinced me that that is inconsistent and wrong, and
that default-value forms in the lambda-list must be included in the
scope.  The implementation of this is easy.  In earlier discussions
I believe it was argued that the implementation is too difficult, but
I think the MAKE-METHOD-FUNCTION proposal reveals that no user needs
to be concerned with the implementation of this scoping, as it is
always done inside of MAKE-METHOD-FUNCTION.

    APPLY-METHOD method next-method-info &REST arguments

This is the only way to call the result of MAKE-METHOD-FUNCTION.
method is the meta-object, not the method-function.
As noted above, my mind could be changed on the arguments to this.

    NEXT-METHOD-INFO

This is in the same category as CALL-NEXT-METHOD and NEXT-METHOD-P.
The only defined operation on its value is to use it as the second
argument to APPLY-METHOD.

    MAKE-NEXT-METHOD-INFO method generic-function list-of-methods

This is a primitive that returns the same kind of abstract value that
NEXT-METHOD-INFO returns, given a concrete list of methods and the
two meta objects that control the method calling sequence.

We could find a better name than "next-method-info".  My only comments
on the name are (a) avoid "continuation", it really means something
else, and (b) include the words "next method(s)" in the name to express
the relationship of this to CALL-NEXT-METHOD.