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