It is convenient for portable metaobjects to be able to memoize information about other metaobjects, portable or otherwise. Because class and generic function metaobjects can be reinitialized, and generic function metaobjects can be modified by adding and removing methods, a means must be provided to update this memoized information.
The dependent maintenance protocol supports this by providing a
way to register an object which should be notified whenever a class or
generic function is modified. An object which has been registered this
way is called a dependent of the class or generic function metaobject.
The dependents of class and generic function metaobjects are maintained with CLOS:ADD-DEPENDENT
and CLOS:REMOVE-DEPENDENT. The dependents of a class or generic function metaobject can be
accessed with CLOS:MAP-DEPENDENTS. Dependents are notified about a
modification by calling CLOS:UPDATE-DEPENDENT. (See the specification of
CLOS:UPDATE-DEPENDENT for detailed description of the circumstances under
which it is called.)
To prevent conflicts between two portable programs, or between portable programs and the implementation, portable code must not register metaobjects themselves as dependents. Instead, portable programs which need to record a metaobject as a dependent, should encapsulate that metaobject in some other kind of object, and record that object as the dependent. The results are undefined if this restriction is violated.
This example shows a general facility for encapsulating metaobjects before recording them as dependents. The facility defines a basic kind of encapsulating object: an updater. Specializations of the basic class can be defined with appropriate special updating behavior. In this way, information about the updating required is associated with each updater rather than with the metaobject being updated.
Updaters are used to encapsulate any metaobject which requires
updating when a given class or generic function is modified. The
function record-updater is called to both create an
updater and add it to the dependents of the class or generic function.
Methods on the generic function CLOS:UPDATE-DEPENDENT, specialized to the
specific class of updater do the appropriate update work.
(defclass updater ()
((dependent :initarg :dependent :reader dependent)))
(defun record-updater (class dependee dependent &REST initargs)
(let ((updater (apply #'make-instance class :dependent dependent
initargs)))
(add-dependent dependee updater)
updater))
A flush-cache-updater simply flushes the
cache of the dependent when it is updated.
(defclass flush-cache-updater (updater) ())
(defmethod update-dependent (dependee (updater flush-cache-updater) &REST args)
(declare (ignore args))
(flush-cache (dependent updater)))
CLOS:UPDATE-DEPENDENT(CLOS:UPDATE-DEPENDENT metaobject
dependent &REST initargs)
metaobjectdependentinitargsThis generic function is called to update a
dependent of metaobject.
When a class or a generic function is reinitialized each of
its dependents is updated. The initargs argument to
CLOS:UPDATE-DEPENDENT is the set of initialization arguments received by
REINITIALIZE-INSTANCE.
When a method is added to a generic function, each of the
generic function's dependents is updated. The initargs argument
is a list of two elements: the symbol ADD-METHOD, and the method
that was added.
When a method is removed from a generic function, each of the
generic function's dependents is updated. The initargs argument
is a list of two elements: the symbol REMOVE-METHOD, and the method
that was removed.
In each case, CLOS:MAP-DEPENDENTS is used to call
CLOS:UPDATE-DEPENDENT on each of the dependents. So, for example, the
update of a generic function's dependents when a method is added
could be performed by the following code:
(CLOS:MAP-DEPENDENTSgeneric-function#'(lambda (dep) (CLOS:UPDATE-DEPENDENTgeneric-functiondep 'add-method new-method)))
Remarks. See Section 29.11, “Dependent Maintenance” for remarks about the use of this facility.
CLOS:ADD-DEPENDENT(CLOS:ADD-DEPENDENT metaobject
dependent)metaobjectdependentThis generic function adds dependent to the
dependents of metaobject. If dependent is already in the set
of dependents it is not added again (no ERROR is SIGNALed).
The generic function CLOS:MAP-DEPENDENTS can be called to access
the set of dependents of a class or generic function. The generic
function CLOS:REMOVE-DEPENDENT can be called to remove an object from
the set of dependents of a class or generic function. The effect of
calling CLOS:ADD-DEPENDENT or CLOS:REMOVE-DEPENDENT while a call to
CLOS:MAP-DEPENDENTS on the same class or generic function is in progress
is unspecified.
The situations in which CLOS:ADD-DEPENDENT is called are not
specified.
Methods
(CLOS:ADD-DEPENDENT
(class STANDARD-CLASS) dependent)No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
(CLOS:ADD-DEPENDENT
(class CLOS:FUNCALLABLE-STANDARD-CLASS) dependent)No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
(CLOS:ADD-DEPENDENT
(generic-function STANDARD-GENERIC-FUNCTION) dependent)No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
Remarks. See Section 29.11, “Dependent Maintenance” for remarks about the use of this facility.
CLOS:REMOVE-DEPENDENT(CLOS:REMOVE-DEPENDENT metaobject
dependent)metaobjectdependentThis generic function removes dependent from the
dependents of metaobject. If dependent is not one of the
dependents of metaobject, no ERROR is SIGNALed.
The generic function CLOS:MAP-DEPENDENTS can be called to access
the set of dependents of a class or generic function. The generic
function CLOS:ADD-DEPENDENT can be called to add an object from the set
of dependents of a class or generic function. The effect of calling
CLOS:ADD-DEPENDENT or CLOS:REMOVE-DEPENDENT while a call to
CLOS:MAP-DEPENDENTS on the same class or generic function is in progress
is unspecified.
The situations in which CLOS:REMOVE-DEPENDENT is called are not
specified.
Methods
(CLOS:REMOVE-DEPENDENT
(class STANDARD-CLASS) dependent)No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
(CLOS:REMOVE-DEPENDENT
(class CLOS:FUNCALLABLE-STANDARD-CLASS) dependent)No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
(CLOS:REMOVE-DEPENDENT
(class STANDARD-GENERIC-FUNCTION) dependent)No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
Remarks. See Section 29.11, “Dependent Maintenance” for remarks about the use of this facility.
CLOS:MAP-DEPENDENTS(CLOS:MAP-DEPENDENTS metaobject
function)metaobjectfunctionfunction to each of
the dependents of metaobject. The order in which the dependents
are processed is not specified, but function is applied to each
dependent once and only once. If, during the mapping,
CLOS:ADD-DEPENDENT or CLOS:REMOVE-DEPENDENT is called to alter the
dependents of metaobject, it is not specified whether the newly
added or removed dependent will have function applied to it.
Methods
(CLOS:MAP-DEPENDENTS
(metaobject STANDARD-CLASS) function)No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
(CLOS:MAP-DEPENDENTS
(metaobject CLOS:FUNCALLABLE-STANDARD-CLASS) function)No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
(CLOS:MAP-DEPENDENTS
(metaobject STANDARD-GENERIC-FUNCTION) function)No behavior is specified for this method beyond that which is specified for the generic function.
This method cannot be overridden unless the following methods are overridden as well:
Remarks. See Section 29.11, “Dependent Maintenance” for remarks about the use of this facility.
| These notes document CLISP version 2.49 | Last modified: 2010-07-07 |