[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Method-lambda and apply-method-lambda
- To: Gregor.pa@XEROX.COM
- Subject: Re: Method-lambda and apply-method-lambda
- From: Patrick H Dussud <DUSSUD@Jenner.csc.ti.com>
- Date: Mon, 4 Apr 88 07:16:49 CDT
- Cc: Common-lisp-object-system@SAIL.STANFORD.EDU
- 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.