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
)
metaobject
dependent
initargs
This 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-DEPENDENTS
generic-function
#'(lambda (dep) (CLOS:UPDATE-DEPENDENT
generic-function
dep '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
)
metaobject
dependent
This 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 SIGNAL
ed).
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
)
metaobject
dependent
This generic function removes dependent
from the
dependents of metaobject
. If dependent
is not one of the
dependents of metaobject
, no ERROR
is SIGNAL
ed.
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
)
metaobject
function
function
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 |