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

DEFINE-METHOD-COMBINATION issues



   Date: Mon, 8 May 89 22:49 EDT
   From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>

   Here are some questions about unclarities in 88-002R revolving around
   method combination, along with my suggested answers.  Any comments?
   I think I will try to use the eventual resolution of this to improve
   the writeup in the ANSI Common Lisp draft specification.

       Can CALL-NEXT-METHOD be called lexically within a MAKE-METHOD?

   p.2-12 says CALL-NEXT-METHOD can be used in the body of a method defined
   by a method-defining form, and 1-22 defines "method-defining form" and
   does not include MAKE-METHOD, so I think that CALL-NEXT-METHOD is not
   specified to work in MAKE-METHOD.  The 2-12 text may have been meant to
   exclude methods created with the chapter 3 function MAKE-METHOD-LAMBDA,
   but in fact it's clear from the draft of chapter 3 that CALL-NEXT-METHOD
   does work in such methods.  So I don't really know what the intent of
   2-12 was, but I think it would be safe to assume that CALL-NEXT-METHOD
   need not be supported in MAKE-METHOD.  Example:

   (call-method (make-method (or (frob) (call-next-method)))
		,remaining-methods)

   could be rewritten:

   (or (frob) (call-method ,(first remaining-methods)
			   ,(rest remaining-methods)))

   See additional discussion below.

       Does CALL-METHOD use the arguments of the effective method, or does it
       use the arguments of the MAKE-METHOD that it was a part of?  For
       example,

	  (DEFMETHOD CHANGE :AROUND (X &OPTIONAL (N 1))
	    (CALL-NEXT-METHOD X (MIN N 0)))

	  (DEFMETHOD CHANGE (X &OPTIONAL (N 2))
	    N)

       What does (CHANGE T 5) return?  A strict reading of the spec says 5,
       but my intuition says 0, and 0 is a lot easier to implement.

   If this is standard method combination, and there are no other methods,
   the effective method is

     (call-method <:around method>
		  ((make-method (call-method <primary method>))))

   and the target of the CALL-NEXT-METHOD is the MAKE-METHOD.
   p.2-11: "The arguments are the arguments that were supplied to the
   effective method form containing the invocation of CALL-METHOD."
   But this is ambiguous, does "the effective method form" mean the whole
   thing, or just the part containing the invocation of CALL-METHOD?  If it
   had meant the whole thing, I think it would have said "the arguments
   that were supplied to the generic function".  Also it makes more sense
   that once call-next-method changes the arguments, they don't "randomly"
   change back to the original arguments.  So I think the example returns
   0.  I propose to change the text on p.2-11 to say "The arguments are the
   arguments that were supplied to the innermost MAKE-METHOD-created
   method enclosing the invocation of CALL-METHOD, or if there is no
   MAKE-METHOD, the arguments that were supplied to the generic function."
   I'd like to say this in fewer words, but couldn't think of a way.

I makes sense. I think  that is the right thing to do.

       Is the effective method code a real Lisp form, i.e. can it contain
       forms which require closures, like:

	  (BLOCK TOO-DEEP
	    (CALL-METHOD ,(FIRST PRE-METHODS)
			 (,@(REST PRE-METHODS)
			  (MAKE-METHOD (RETURN-FROM TOO-DEEP NIL))))
	    (CALL-METHOD ,(FIRST POST-METHODS)
			 (,@(REST POST-METHODS)
			  (MAKE-METHOD T))))

   Nothing in chapter 1 or 2 mentions any restrictions on what the
   effective method form can do, so the answer should be yes.  The
   problem is that the description of MAKE-METHOD (p.2-11) fails to
   specify the lexical environment of the form its given.  Nor does
   anything specify the lexical environment of the overall effective
   method form.  After thinking about it a bit, I believe the intention
   was that both of these forms are in the null lexical environment.
   Thus the answer is that this example code is not valid.

   Unless there are further comments, I propose to change the ANSI
   Common Lisp specification to say both effective method forms and
   MAKE-METHOD forms are in the null lexical environment.  Note that
   this implies no CALL-NEXT-METHOD inside of MAKE-METHOD.  And no
   CONTINUE-WHOPPER inside of a DEFWRAPPER, to translate back to
   Flavors terminology.

The only comment I have is that I don't know if it is going to be seen as a
drastic constraint or not. I'd like to see others opinion on this.

       In 12/15/88 MOP Draft number 10, some places seem to think that a
       METHOD-COMBINATION object consists of the information supplied to
       DEFGENERIC (with a mysterious "Documentation" slot), and other places
       seem to think that it consists of the information supplied to
       DEFINE-METHOD-COMBINATION, but the slots only make sense for the short
       form.

I agree with what was said and I don't think we need to change the document.

   The issue here is that p.2-34 says "If lambda-list is not congruent to
   the generic function's lambda-list, additional ignored parameters are
   automatically inserted until it is congruent", but this doesn't say
   where they are inserted nor what happens if inserting additional
   parameters can't make it congruent (e.g. too many required parameters
   to begin with).  Are they inserted at the end?  At the end of each
   group (required, optional, keyword)?  At the beginning??

   We thought about simplifying this to just require the two lambda-lists
   to be congruent, but that doesn't work well since a single method
   combination type should be useable with many different generic functions
   with different lambda-lists.

   I think the best answer is to delete the stuff about congruence (the
   last two sentences of the first paragraph on p.2-34) and simply say what
   happens if the arguments supplied to the generic function don't match
   the lambda-list: if there are too few arguments, NIL is assumed for
   missing arguments.  If there are too many arguments, the extra arguments
   are ignored.  If there are unhandled keyword arguments, they are
   ignored.  Supplied-p parameters work in the normal fashion.  Default
   value forms are evaluated in the null lexical environment (except for
   bindings of :ARGUMENTS parameters to their left, of course).  This is
   more or less what the equivalent Flavors feature does.  Any objections?

   Also, what happens if the effective method form returned by your
   body forms includes (setq ,variable ...) or (setf ,variable ...),
   where variable is one of the :ARGUMENTS parameters?  I think
   the consequences should be undefined.


All of this sound good.