[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
call-next-method incoherency
Here are some arguments from JonL which I find quite persuasive.
Before I saw these I was just going to go with #1 since that's
what all the respondents had said, but now I am reconfirmed in my
belief that #3 is the best option. Did the people who suggested
#1 base their suggestion on careful thought, or just pick that one
because it seemed easiest or was first on the list? If there are
good arguments for #1 I'd like to hear them.
#1 smacks of overloading a communication channel. Some lusers out there
will come to depend on finding out the method-combination mismatch
error by placing obscure methods on NO-NEXT-METHOD, so we will never
be able to correct this wort once it gets in.
#4 smacks of overkill; a piece of syntax at the same level as everything
else in method combination to cover an incredibly obscure problem that
almost no one will run into. Why clutter up the spec. Besides, whole
method groups might be too coarse a sieve to strain out the contexts
under which you want to proscribe CALL-NEXT-METHOD.
#3 is a very logical extension of the meaning of CALL-METHOD as spelled
out in 88-002R p.2-11. CALL-METHOD should bear the burden, since it
is the interface between method-combination and CALL-NEXT-METHOD. I
suspect some existing implementations (e.g. PCL) would require more of
a change to do it this way than by #1, but not a radical change.
#2 is just a variant of #3, but the syntax is more "special case", rather
than the "natural extesion" of #3. Providing a null list for the
next-methods argument is a fine way to say "any use of CALL-NEXT-METHOD
will simply call NO-NEXT-METHD"; the natural way to differentiate this
case from a control-error case is to _not_ provide the next-methods
argument at all. Thus #3 is preferable.
The argument would be compelling if you could show a way to model the
prohibitions in standard-method-combination using this #3 approach
(i.e., can't use CALL-NEXT-METHOD in :before or :after methods, but can
use it in primary and :around).
That's the end of the quotation from JonL, the rest is my response:
From the documentation examples, here is the existing definition of
standard method combination:
;The default method-combination technique
(define-method-combination standard ()
((around (:around))
(before (:before))
(primary () :required t)
(after (:after)))
(flet ((call-methods (methods)
(mapcar #'(lambda (method)
`(call-method ,method ()))
methods)))
(let ((form (if (or before after (rest primary))
`(multiple-value-prog1
(progn ,@(call-methods before)
(call-method ,(first primary)
,(rest primary)))
,@(call-methods (reverse after)))
`(call-method ,(first primary) ()))))
(if around
`(call-method ,(first around)
(,@(rest around)
(make-method ,form)))
form))))
and here is the compelling modified version for the #3 approach:
;The default method-combination technique
(define-method-combination standard ()
((around (:around))
(before (:before))
(primary () :required t)
(after (:after)))
(flet ((call-methods (methods)
(mapcar #'(lambda (method)
`(call-method ,method))
methods)))
(let ((form (if (or before after (rest primary))
`(multiple-value-prog1
(progn ,@(call-methods before)
(call-method ,(first primary)
,(rest primary)))
,@(call-methods (reverse after)))
`(call-method ,(first primary) ()))))
(if around
`(call-method ,(first around)
(,@(rest around)
(make-method ,form)))
form))))
Only one line is changed.