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

*To*: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>*Subject*: Re: MAKE-METHOD-FUNCTION and APPLY-METHOD*From*: kempf@Sun.COM*Date*: Wed, 13 Apr 88 17:06:22 -0700*Cc*: kempf@Sun.COM, common-lisp-object-system@SAIL.STANFORD.EDU*In-reply-to*: Your message of Wed, 13 Apr 88 14:31:00 -0400. <19880413183155.2.MOON@EUPHRATES.SCRC.Symbolics.COM>

>But compute-effective-method has to be generic! That's the whole basis of >the meta-objectification of method combination. If this is another >non-terminating circularity, then it's another defect in the meta-circular >description of CLOS. In an implementation all these circularities have to >be broken by special-casing, as in any meta-circular interpreter. OK, I'll buy that. I misunderstood the specification for compute-effective-method. Further comment on the implications below, plus the special casing which is needed. >What compute-effective-method returns is neither a function nor a method >object. It actually returns a Lisp form. See 88-002 p.1-32. This Right. That explains what the undocumented function make-effective-method-function does in the example on pg. 3-59. It takes the generic function and the effective method form, and returns a function which can be applied to start the method rolling. It also hides the implementation dependencies necessary for setting up the environment so that call-next-method works. And that is where the metacircular recursion bottoms out, since it returns a function and not a generic function. >I can't be sure your code is wrong since I have >yet to see a satisfactory explanation of what compute-discriminator-code >is for. compute-discriminator-code does precisely the same thing for generic dispatch that compute-effective-method does for method combination. It is where code for customized generic dispatch gets generated. It needs to work together with make-method-function to assure that customized control flow changes like call-next-method get done correctly, because the generic dispatch code has to know what sort of interface the method functions require and what specialized features of the execution environment need to be set up. In the default case, make-effective-method-function takes care of most of that. Here's what I'd expect compute-discriminator-code to look like in the default case: (defmethod compute-discriminator-code ((generic-function standard-generic-function) (method-combination standard-method-combination) ) #'(lambda (&rest args) (let* ( (applicable-methods (compute-applicable-methods generic-function args) ) (effective-method-form (compute-standard-effective-method-form generic-function method-combination applicable-methods ) ) (effective-method-function (make-effective-method-function generic-function effective-method-form ) ) ) (check-keyword-arguments generic-function methods args) (apply effective-method-function args) ) ) ;lambda ) ; compute-discriminator-code There are a couple things to note here: 1) Everything called by compute-discriminator-code is a function. These are: compute-applicable-methods, compute-standard-effective-method-form, and make-effective-method-function. If this is not the case, the metacircularity does not bottom out. 2) New in this list is compute-standard-effective-method-form. It takes the generic function, a standard-method-combination object, and the list of applicable methods, and returns the effective method form. The compute-effective-method method for standard-method-combination would have the application of this function as its body. This is the special casing. Side note: the method combination object might not be needed as an argument, since the function already knows the kind of method combination. 3) The creation of the dispatcher function is parameterized by both the generic function and the method combination. There is really no choice here, because the algorithm for calculating the effective method depends on both the list of applicable methods (which the generic function provides) and the method combination type. 4) Functions similar to compute-standard-effective-method-form would be needed for other system provided method combination types, of course. I think some of the problems in the discussion about bottoming out of metacircularity come from the fact that we made method combination metacircular without taking into account that calculating the effective method, which is parameterized by method combination, is a fundamental part of generic dispatch, and therefore we introduced an infinite loop. This proposal unrolls the loop. As an example of how this could be used with make-method-function to introduce a customized control flow primitive, consider the following modification, which we had suggested in the specification paper. It allows any more general method to be invoked, depending on the arguments, rather than just the next most general method: ;;uses no method combination, and simply takes the first method ;; on the list to start the ball rolling. (defmethod compute-discriminator-code ((generic-function my-generic-function) method-combination) #'(lambda (&rest args) (let* ( (applicable-methods (my-compute-applicable-methods generic-function args) ) ) (apply (method-function (car applicable-methods)) (cdr applicable-methods) args ) ) ) ;lambda ) ; compute-discriminator-code (defmethod make-method-function ((method my-method) (generic-function my-generic-function) specializers qualifiers lambda-exp &optional macroexpand-env ) `(lambda (rest-applicable-methods &rest args) (flet ( (my-call-next-method (&rest call-args) (let* ( (matching-method (get-more-general-method rest-applicable-methods call-args) ) (next-rest-applicable-methods (member matching-method rest-applicable-methods) ) ) (if matching-method (apply (method-function matching-method) (cdr next-rest-applicable-methods) call-args ) (apply #'no-applicable-method ,generic-function call-args) ) ) ;let* ) ;my-call-next-method ) (apply (function ,lambda-exp) args) ) ;flet ) ;lambda ) ;make-method-function Here, compute-discriminator-code and make-method-function implement the communication of the applicable method list via a hidden argument. The only thing I don't like about this is that compute-discriminator-code returns a function object while make-method-function returns the code for a function (maybe the names should be interchanged?). But, given that function objects are atomic in Common Lisp, there probably isn't any better way to do this, except by having compute-discriminator-code return the code, so the caller would have to turn it into a function, or have make-method-function call eval on the code to make the function. Does this make any sense? The fact that we're having such a hard time converging on this is an indication to me that we're venturing into little understood territory. However, as Gregor mentioned, we need to come to convergence on this soon. jak

**Follow-Ups**:**Re: MAKE-METHOD-FUNCTION and APPLY-METHOD***From:*David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>

**References**:**Re: MAKE-METHOD-FUNCTION and APPLY-METHOD***From:*David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>

- Prev by Date:
**Re: Chapter 1 and 2 Last Chance Review** - Next by Date:
**Responses** - Previous by thread:
**Re: MAKE-METHOD-FUNCTION and APPLY-METHOD** - Next by thread:
**Re: MAKE-METHOD-FUNCTION and APPLY-METHOD** - Index(es):