Hi,
I need some help with a design decision in AspectL. In AspectL, special generic functions currently need to be defined like this:
(define-special-function some-function (x y z) (:definer some-function*))
The :definer option names a generic function that must be used to add methods to whereas the "main" name (some-function) is the function that must be used for calling the special function. ("Caller" and "definer" must be separated in order to make the whole concept work at all.)
Furthermore, methods need to be defined like this:
(defmethod some-function* ((scope t) x y z) ...)
or, if you want to define a method in the current dynamic scope:
(defmethod* some-function* ((scope dynamic) x y z) ...)
The defmethod* operator must be used in the latter case because most CLOS implementations do not provide correct implementations of defmethod as specified in AMOP, and I rely on that. (Actually, I rely on the fact that make-method-lambda is called, but some CLOS implementations don't provide make-method-lambda at all, and those that do don't call it in the defmethod macro.)
Furthermore, the first specializer (t or dynamic) is used to make the method dispatch work, so that only methods that are valid for the current dynamic scope are actually executed.
This design has "evolved" over a few iterations, and by now I think it's a mess. Here is what I would actually prefer:
- Special generic functions should be defined like this:
(defgeneric some-function (x y z) (:generic-function-class special-function))
- Methods on special functions should be defined like this:
(defmethod some-function (x y z) ...)
or
(defmethod some-function (x y z) (:scope dynamic) ...)
I have experimented with various ways to achieve this, and I am confident by now that this would work. However, I would need to reimplement the defmethod and maybe even the defgeneric macro.
There are some pros and cons and here:
Pros:
p1) It looks better and more in line with how CLOS is "traditionally" used.
p2) The new defmethod macro would provide a way to pass method options, a feature that is currently missing in CLOS. For example, it's not currently not possible to name the method class for a method. With the new defmethod macro, this would work as follows:
(defmethod do-something (a b c) (:method-class non-standard-method) ...)
The idea is that not only strings and declarations are processed specially, but also all forms that are conses and start with a keyword. This is ok AFAICS, because conses that start with a keyword cannot be executed in a meaningful way anyway.
p3) The new defmethod and defgeneric macros would conform to the AMOP specification which could be worthwhile for other purposes beyond AspectL as well. (There is already a MOP utilities package provided as part of AspectL that is not strictly related to AspectL and could already be used separately.)
Cons:
c1) I need to shadow defmethod and maybe defgeneric. This would have an impact on applications and libraries that want to use AspectL.
c2) I don't know (yet?) how to ensure the compile-time semantics of those operators as specified in the ANSI spec. The various CLOS implementations do this differently and AMOP doesn't specify anything in this regard.
c3) I don't know how to interact with the several development environments that want to record, for example, source locations of method definitions, etc.
c1 can possibly be solved by using different names, but I want to avoid that. I don't see any strong reasons to avoid shadowing just because of shadowing.
Maybe I can solve c2 in some ways, and I would try to do that, but I don't yet see how.
I will probably have no time to solve c3 (but I would accept patches to make this work).
I am currently strongly in favor of dropping define-special-function/defmethod* and switching to defgeneric/defmethod as sketched here, but I would appreciate to hear some other opinions, no matter whether strong or not.
So what do you think?
Pascal