The generic function `compute-effective-method-function-from-classes`

is called by LispWorks to compute the effective method function when *gf* is called with required argument types specified by *classes*. If *em-function* is `nil`

, then `no-applicable-method`

is called. Otherwise, *em-function* may be cached by the generic function and is called with the arguments supplied to the generic function.

The default method for `compute-effective-method-function-from-classes`

implements the standard generic function behavior of finding the applicable methods and using the method combination to construct a function that calls them.

In order for `compute-effective-method-function-from-classes`

to be called and the result cached, there must be methods specializing on the "interesting" arguments. For the standard behavior, this is trivially true, but if you want to implement other behavior then you need to define dummy methods even if they are never called.

A "computed" generic function that returns a value based on a form chosen from the classes of the arguments rather than the methods. Note the dummy method which is specialized on null.

(defclass computed-generic-function (standard-generic-function)

((computer :initarg :computer

:accessor computed-generic-function-computer))

(:metaclass funcallable-standard-class))

(defmethod clos:compute-effective-method-function-from-classes

((gf computed-generic-function)

classes)

(apply (computed-generic-function-computer gf) gf classes))

(defmacro define-computed-generic-function (name lambda-list

specializers

&body body)

`(dspec:def (define-computed-generic-function ,name)

(defgeneric ,name ,lambda-list

(:generic-function-class computed-generic-function)

(:method ,(loop for arg in lambda-list

collect

(if (member arg specializers)

`(,arg null)

arg))))

(setf (computed-generic-function-computer #',name)

#'(lambda (,name ,@(loop for arg in lambda-list

collect

(if (member arg specializers)

arg

(gensym))))

,@body))

',name))

(define-computed-generic-function aaaa (x y) (x)

(let ((something (compute-something aaaa x)))

#'(lambda (x y)

(declare (ignore y))

(format nil "Something for ~a is ~a" x something))))

(defun compute-something (gf class)

(format nil "~a-~a"

(generic-function-name gf)

(class-name class)))

*LispWorks User Guide and Reference Manual - 13 Feb 2015*