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

Re: method-lambda and apply-method-lambda



[Sorry about the length of this message.  I couldn't find anything
to delete without losing the sense of the conversation.]

    Date: Mon, 11 Apr 88 14:33:03 -0700
    From: kempf@Sun.COM

	>    APPLY-METHOD method next-method-info &REST arguments

	I don't think this generic function is really necessary, 
	since APPLY, being itself
	implementation dependent, could be modified to do the right thing given
	a method function. 

      Jim, I think you must have missed the point.  The problem isn't that what
      APPLY does is implementation-dependent, but that the arguments to be passed
      to APPLY are implementation-dependent.  The most obvious case is the
      next-method-info info; there is no way for APPLY to deduce this from the
      other arguments, is there?  If there is a way, I might change my mind on
      suggesting a separate APPLY-METHOD primitive, but if there isn't a way,
      we have to have that primitive so that the caller can supply the information.

    Why does the next method info have to be passed as arguments to APPLY or
    an APPLY-like function in the first place? I thought the whole purpose of 
    MAKE-METHOD-FUNCTION was to return a function for which that information
    has already been installed in the (some) environment, or maybe I'm missing
    something. And that NEXT-METHOD-INFO gets it. 

MAKE-METHOD-FUNCTION can only depend on static information, which is the
same every time the method is called.  That's because MAKE-METHOD-FUNCTION
is called once and the result is stored as the method-function
conceptual-slot of the method meta-object.  MAKE-METHOD-FUNCTION isn't
called every time the generic function is called, as I understand it.  The
NEXT-METHOD-INFO is dynamic information since it depends on what other
methods are also applicable, which can vary from one call to the next.

			   Some implementations of APPLY 
	already must differentiate based on whether the function object is a closure
	or not, since in the former case, the lexical environment must be
	modified to reflect the lexical environment of the closure, so the
	additional case of a method function is probably nothing new.
	However, it might be useful for metaobject programmers who want a hook
	for a metaclass specific way of applying a method. In that case, I think
	the NEXT-METHOD-INFO argument could be dropped, since the concept of
	a next method is specific to STANDARD-METHOD. 

      I disagree.  I think CALL-NEXT-METHOD should be available to all classes
      of methods that want it; I don't think it should be something magic for
      standard-method.

    No, I didn't mean to imply that CALL-NEXT-METHOD would be magic. Look, 
    here's my vanillia implementation for MAKE-METHOD-FUNCTION for STANDARD-METHOD:

    (defmethod make-method-function 
      ((proto-method standard-method)
       (generic-function standard-generic-function)
       specializers
       qualifiers
       lambda-exp
       &optional macroexpand-env
      )

      `(flet 
	    ( (call-next-method (&rest args)
		(if (check-args args ',specializers)
		  (apply (get-next-method-function ',proto-method) args)
		  (apply #'no-applicable-method ',generic-function args)
		)
	      )
	    )
	    ,lambda-exp
	)
    )

    The only "magic" here is GET-NEXT-METHOD-FUNCTION, and I can't think
    of any other way to keep track of the next method function unless
    the method knows about it's next method itself 
    (though there may be some ways to speed
    up getting it, but this is a specification). Is there something
    I'm missing here?

Maybe there's something I'm missing, because I can't imagine what the
implementation of GET-NEXT-METHOD-FUNCTION could possibly be.  I just
don't see from where it can figure out what method to call.  That
depends on the current method's position in the precedence-ordered
list of applicable methods with relevant qualifiers, and I don't see
how GET-NEXT-METHOD-FUNCTION can find either of those quantities.
That's why I think there has to be a "next-method-info" object that
gets passed around as an extra argument.  One implementation of
call-next-method would be to funcall the car of next-method-info,
passing the cdr of next-method-info to it.  CLOS shouldn't mandate
that it be a list, though.

						      The method metaclass method
	for this generic function would then implement any special processing
	for changing control flow.

      I don't think I understand this last sentence; do you have a specific proposal?

    (defmethod apply-method ((method standard-method) &rest arguments)

      (apply (method-function method) arguments)
    )

    Other metaclasses might want to control method application via their
    method metaclass object, but the default would be not to.

I still don't understand, but that's probably irrelevant for now.

    I think I've got a different (and perhaps wrong?) model about what's
    going on. My model is that MAKE-METHOD-FUNCTION constructs a function
    in which the metaclass dependent specialized control flow primitives
    (e.g. CALL-NEXT-METHOD) are part of the lexical environment
    seen by the user code (LAMBDA-EXP). 

That's my model too.

					Any other system dependent 
    information needed to influence control flow (e.g. permutation tables)
    would also need to be included, but naming access controlled so only system
    code sees it. 

Agreed (except permutation tables may be only for data access, not for
control flow; that in fact depends on the implementation, and we have
tried it both ways.  Right now we do some control flow there and other
control flow elsewhere.)

		  NEXT-METHOD-INFO, or whatever the accessor function
    is named, is able to get at that information in some implementation
    dependent way. 

Agreed.

		   Thus, the method function should be invokable via 
    APPLY, with APPLY-METHOD more of a utility should a metaobject user
    happen to have a method and not want to retieve the function.
    want to use it. No hidden arguments to APPLY needed.

Non-sequitur.  The fact that CALL-NEXT-METHOD is part of the lexical
environment does not mean that the body of CALL-NEXT-METHOD contains no
free variables.  Indeed, since CALL-NEXT-METHOD in a given method does not
do the same thing every time it is called, it must depend in some way on a
free variable or the equivalent.  A lot of this discussion is about how to
model that free variable and how abstract to be about it.  For instance, if
we wanted to totally constrain implementation techniques, we could do
something like setf-functions and say "every method-function takes one
extra argument, before the arguments visible in defmethod, and the value of
this argument is a list of method functions.  The parameter bound to this
argument is named CLOS-SYSTEM-INTERNALS::NEXT-METHOD-LIST and
CALL-NEXT-METHOD works by funcalling its car, passing its cdr as the first
argument."  I don't think being so concrete would be wise, and I don't
think it's necessary either.  We shouldn't say what form that information
is represented in (maybe it's an array rather than a list, maybe the
entries are method meta-objects, rather than method-functions, or maybe the
entries are machine program counter values), and we shouldn't say through
what path the information is delivered (maybe it's passed in machine
register A5, rather than being passed as a Lisp argument; maybe it's
stashed in a special variable).  But we do have to recognize that the
information exists and if we want to be able to do things like tracing
methods we have to provide a way to transmit the information from one
function to another.

Okay, where does this mysterious "information" come from in the first place?
My model is that the generic function dispatch produces not only a method
function to be called, but also this extra information to be passed to it.
Thus it's a function of the argument classes (or identities) that gets
precomputed and stored in the method lookup tables.  Just as we don't
dictate that any particular form of method lookup tables be used, even
though every implementation has to have them in some form, we shouldn't
dictate any particular form of this information, nor should we dictate
whether it is precomputed or calculated on demand when call-next-method
is done (if you were assuming we always calculate it on demand, you have
to think about what information is required to calculate it).