[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
call-method proposal prime prime
- To: common-lisp-object-system@SAIL.STANFORD.EDU
- Subject: call-method proposal prime prime
- From: Gregor.pa@Xerox.COM
- Date: Mon, 11 Jan 88 21:18 PST
- Fcc: BD:>Gregor>mail>outgoing-mail-1.text
- Line-fold: no
- Supersedes: <880111184514.5.GREGOR@SPIFF.parc.xerox.com>
Pavel pointed out that I lost while trying to compensate for previous
lossage. At least I know Pavel is reading these messages. This message
entirely supersedes the messages I sent earlier.
I spent some time thinking about how to solve the problem with
make-method-call and concluded that make-method-call was a really
complex little bugger. I have come up with a mechanism I believe is
simpler, on first examination it appears to be missing the single method
optimization but I believe that can be fixed quite easily.
This description is not entirely adequate, but I hope its enough to
convey the flavor of this proposal.
This proposal uses two lexical macros, CALL-METHOD and EFFECTIVE-METHOD.
These macros are lexically bound within the scope of an effective method
body. That means that the body of define-method-combination is allowed
to return code that uses these macros. Code walkers can understand
these macros quite easily, I believe their semantics is also easier for
programmers to understand.
The differences between this and make-method-call in the spec are:
- these are lexical macros
- the functionality of automatically converting lists to
combined methods provided by make-method-call is not
provided by call-method. Instead, the effective method
lexical macro must be used to declare that a form is
itself an effective method being used in the call-next-method
list.
- call-method accepts two required arguments. The method to
call is the first argument. The next methods accesible from
that method is the second argument.
- support for :operation and :identity-with-one-argument is
missing. I believe this makes things simpler. I also believe
we can get that optimization back quite easily.
The biggest difference is that I find this conceptually simpler to
understand. When I see call-method, I don't have to think about the
three different forms the first argument to make-method-call can have, I
know the first argument must be a method. I know the second argument
must be a list of methods or effective-method forms.
Here are implementations of standard and and method combination written
using this mechanism. I have read them over, I believe they are right,
but I don't have an implementation of this so I can't be sure.
(define-method-combination standard ()
((around (:around))
(before (:before))
(primary () :required t)
(after (:after)))
(let ((effective
;; This is the real method that gets run once all of the
;; :around methods have call-next-method'ed to get to it.
`(effective-method
(multiple-value-prog1
(progn
,@(mapcar #'(lambda (m) `(call-method ,m ()))
before)
(call-method ,(car primary) ,(cdr primary)))
,@(mapcar #'(lambda (m) `(call-method ,m ()))
(reverse after))))))
(if around
`(call-method ,(car around)
,(append (cdr around) (list effective)))
`(call-method ,effective ()))))
(define-method-combination and (&optional (order ':most-specific-first))
((around (:around))
(primary (and) :order order :required t))
(let ((effective
`(effective-method
(and (mapcar #'(lambda (m) `(call-method ,m ()))
primary)))))
(if around
`(call-method ,(car around)
,(append (cdr around) (list effective)))
`(call-method ,effective))))
-------