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


The CLOS MOP doesn't define a function like
GENERIC-FUNCTION-EFFECTIVE-METHOD, though i think it would be quite
easy to do and fairly useful:

The CLOS spec suggests that the internals of a generic generic
function might look something like:

(lambda (&rest args)
  ;; Find the effective method.
  (let ((m (apply #'generic-function-effective-method .gf. args)))
    (if m (apply m args)  ; Run it.
          (apply #'no-applicable-method .gf. args))))

Where .gf. is the generic function we are trying to run.  Although it
would be very slow to actually do it this way, it nicely separates the
method discrimination from the application of the effective method
(which really isn't a method, is it?).

PCL avoids doing this at all cost, in fact it tries to combine
discrimination and effective method application as tightly as
possible.  However, a programmer might occasionally use this:

EXAMPLE 1:  Pull discrimination out of a loop:

;;; Rather than:
(dotimes (i 10000)
  (generic-frob object))

;;; One could write:
(let ((m (generic-function-effective-method generic-frob object)))
  (dotimes (i 10000)
    (funcall m object)))  ; Hope no one is redefining generic-frob.

OK, so ideally where only saving a few instructions, BUT they can add up.

EXAMPLE 2:  Method delegation.

The essence of method delegation is:

(defclass delegate-mixin
  ((delegate-to :initform nil
		:initarg :delegate-to
		:reader delegate-to)))

(defmethod delegate-to ((thing t))
  ;; Normally don't delegate.

(defmethod delegate ((gf standard-generic-function) &rest args)
  ;; Delegate is like apply.
    (let ((method (apply #'find-delegated-method gf args)))
      (if method (apply method args)
	(apply #'buck-stops-here gf args))))

(defmethod find-delegated-method ((gf standard-generic-function)
				  (client delegate-mixin) &rest args)
  (let ((server (delegate-to client)))
    (if server
	(apply #'generic-function-effective-method gf server args))))

(defmethod no-applicable-method
    ((gf standard-generic-function) &rest args)
    ;; Try delegation.
  (apply #'delegate gf args))

OK, so it isn't fast, but it works.  I think it would be useful to
have such generic functions as GENERIC-FUNCTION-EFFECTIVE-METHOD for
meta level hacking.  I realize it adds more to the languages, but it
does make small extentions easier, and more portable, and has good
expository value.