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

Method-lambda and apply-method-lambda



From:    Patrick H Dussud <DUSSUD@Jenner>
To:      Gregor.pa@XEROX.COM
Cc:      Common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Method-lambda and apply-method-lambda
In-Reply-To: Msg of Mon, 28 Mar 88 11:35 PST from Gregor.pa@XEROX.COM

     Date: Mon, 28 Mar 88 11:35 PST
     From: Gregor.pa@XEROX.COM
     Subject: Method-lambda and apply-method-lambda
     
         Date: Fri, 25 Mar 88 14:38:09 CST
         From: Patrick H Dussud <DUSSUD@Jenner.csc.ti.com>
     
     I have two kinds of comments about your proposal.  I have some minor
     comments about the details of the proposal itself as well as some
     serious questions about whether it can work.
     
     I will start with the minor nits.
     
         make-method-function GENERIC-FUNCTION QUALIFIERS SPECIALIZERS
                              LAMBDA-FORM &optional MACROEXPAND-ENVIRONMENT
     
     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.

     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?


Good idea. I didn't put a method in there because I was under the impression
that the modularity of the contract is broken. The way compute-effective-method
is designed, the contract between the generic function and the method, abstracted
by the local macro call-method will not depend on the method. Maybe I didn't
look hard enough.
     
     
     Also, I am pretty sure we want to make compile work on these, which
     brings me to my second point.
     
     How does one write the following code in your proposal:
     
     (defun advise-1-arg-method (method)
       (let ((function (method-function method)))
         (reinitialize-instance method
            :function #'(method-lambda (a)
                          (format *trace-output* "~&Got arg ~S" a)
                          (funcall function a)))))


You can do:
(defun advise-1-arg-method (method)
  (let ((function (method-function method)))
    (reinitialize-instance method
			   :function
			   (make-method-function
			     (method-generic-function method)
			     (method-qualifiers method)
			     (method-parameter-specializers  method)
			     `(lambda (a)
				(format *trace-output* "~&Got arg ~S" a)
				(funcall ,function a)))lambda-form )))
 
     
     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 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.

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:

Expand-method-function GENERIC-FUNCTION QUALIFIERS SPECIALIZERS
                       LAMBDA-FORM &optional MACROEXPAND-ENVIRONMENT
which produces something like:
(function (lambda ....)). Note that what it produces is implementation dependent
and can substitute lambda for something else.

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. 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.

Patrick.