29.1. Meta-Object Protocol

Adapted from chapters 5 and 6 of [AMOP]

29.1.1. Introduction
29.1.1.1. Notation
29.1.1.2. Package
29.1.2. Overview
29.1.2.1. Metaobjects
29.1.2.1.1. Classes
29.1.2.1.2. Slot Definitions
29.1.2.1.3. Generic Functions
29.1.2.1.4. Methods
29.1.2.1.5. Specializers
29.1.2.1.6. Method Combinations
29.1.2.2. Inheritance Structure of Metaobject Classes
29.1.2.2.1. Implementation and User Specialization
29.1.2.3. Processing of the User Interface Macros
29.1.2.3.1. Compile-file Processing of the User Interface Macros
29.1.2.3.2. Compile-file Processing of Specific User Interface Macros
29.1.2.4. Metaobject Initialization Protocol
29.1.3. Classes
29.1.3.1. Macro DEFCLASS
29.1.3.2. Inheritance Structure of class metaobject Classes
29.1.3.3. Introspection: Readers for class metaobjects
29.1.3.3.1. Generic Function CLASS-NAME
29.1.3.3.2. Generic Function CLOS:CLASS-DIRECT-SUPERCLASSES
29.1.3.3.3. Generic Function CLOS:CLASS-DIRECT-SLOTS
29.1.3.3.4. Generic Function CLOS:CLASS-DIRECT-DEFAULT-INITARGS
29.1.3.3.5. Generic Function CLOS:CLASS-PRECEDENCE-LIST
29.1.3.3.6. Generic Function CLOS:CLASS-DIRECT-SUBCLASSES
29.1.3.3.7. Generic Function CLOS:CLASS-SLOTS
29.1.3.3.8. Generic Function CLOS:CLASS-DEFAULT-INITARGS
29.1.3.3.9. Generic Function CLOS:CLASS-FINALIZED-P
29.1.3.3.10. Generic Function CLOS:CLASS-PROTOTYPE
29.1.3.3.11. Methods
29.1.3.4. Class Finalization Protocol
29.1.3.5. Class Initialization
29.1.3.5.1. Initialization of class metaobjects
29.1.3.5.2. Reinitialization of class metaobjects
29.1.3.6. Customization
29.1.3.6.1. Generic Function (SETF CLASS-NAME)
29.1.3.6.2. Generic Function CLOS:ENSURE-CLASS
29.1.3.6.3. Generic Function CLOS:ENSURE-CLASS-USING-CLASS
29.1.3.6.4. Generic Function CLOS:FINALIZE-INHERITANCE
29.1.3.6.5. Generic Function MAKE-INSTANCE
29.1.3.6.6. Generic Function ALLOCATE-INSTANCE
29.1.3.6.7. Generic Function CLOS:VALIDATE-SUPERCLASS
29.1.3.6.8. Generic Function CLOS:COMPUTE-DIRECT-SLOT-DEFINITION-INITARGS
29.1.3.6.9. Generic Function CLOS:DIRECT-SLOT-DEFINITION-CLASS
29.1.3.6.10. Generic Function CLOS:COMPUTE-CLASS-PRECEDENCE-LIST
29.1.3.6.11. Generic Function CLOS:COMPUTE-SLOTS
29.1.3.6.12. Generic Function CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION
29.1.3.6.13. Generic Function CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS
29.1.3.6.14. Generic Function CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS
29.1.3.6.15. Generic Function CLOS:COMPUTE-DEFAULT-INITARGS
29.1.3.7. Updating Dependencies
29.1.3.7.1. Generic Function CLOS:ADD-DIRECT-SUBCLASS
29.1.3.7.2. Generic Function CLOS:REMOVE-DIRECT-SUBCLASS
29.1.4. Slot Definitions
29.1.4.1. Inheritance Structure of slot definition metaobject Classes
29.1.4.2. Introspection: Readers for slot definition metaobjects
29.1.4.2.1. Generic Functions
29.1.4.2.2. Methods
29.1.4.2.3. Readers for direct slot definition metaobjects
29.1.4.2.4. Readers for effective slot definition metaobjects
29.1.4.3. Initialization of slot definition metaobjects
29.1.4.3.1. Methods
29.1.5. Generic Functions
29.1.5.1. Inheritance Structure of generic function metaobject Classes
29.1.5.2. Introspection: Readers for generic function metaobjects
29.1.5.2.1. Generic Function CLOS:GENERIC-FUNCTION-NAME
29.1.5.2.2. Generic Function CLOS:GENERIC-FUNCTION-METHODS
29.1.5.2.3. Generic Function CLOS:GENERIC-FUNCTION-LAMBDA-LIST
29.1.5.2.4. Generic Function CLOS:GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER
29.1.5.2.5. Generic Function CLOS:GENERIC-FUNCTION-DECLARATIONS
29.1.5.2.6. Generic Function CLOS:GENERIC-FUNCTION-METHOD-CLASS
29.1.5.2.7. Generic Function CLOS:GENERIC-FUNCTION-METHOD-COMBINATION
29.1.5.2.8. Methods
29.1.5.3. Initialization of Generic Functions
29.1.5.3.1. Macro DEFGENERIC
29.1.5.3.2. Generic Function Invocation Protocol
29.1.5.3.3. Initialization of generic function metaobjects
29.1.5.4. Customization
29.1.5.4.1. Generic Function (SETF CLOS:GENERIC-FUNCTION-NAME)
29.1.5.4.2. Generic Function ENSURE-GENERIC-FUNCTION
29.1.5.4.3. Generic Function CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS
29.1.5.4.4. Generic Function ADD-METHOD
29.1.5.4.5. Generic Function REMOVE-METHOD
29.1.5.4.6. Generic Function CLOS:COMPUTE-APPLICABLE-METHODS
29.1.5.4.7. Generic Function CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES
29.1.5.4.8. Generic Function CLOS:COMPUTE-EFFECTIVE-METHOD
29.1.5.4.9. Function CLOS:COMPUTE-EFFECTIVE-METHOD-AS-FUNCTION
29.1.5.4.10. Generic Function CLOS:MAKE-METHOD-LAMBDA
29.1.5.4.11. Generic Function CLOS:COMPUTE-DISCRIMINATING-FUNCTION
29.1.6. Methods
29.1.6.1. Inheritance Structure of method metaobject Classes
29.1.6.2. Introspection: Readers for method metaobjects
29.1.6.2.1. Generic Function CLOS:METHOD-SPECIALIZERS
29.1.6.2.2. Generic Function METHOD-QUALIFIERS
29.1.6.2.3. Generic Function CLOS:METHOD-LAMBDA-LIST
29.1.6.2.4. Generic Function CLOS:METHOD-GENERIC-FUNCTION
29.1.6.2.5. Generic Function CLOS:METHOD-FUNCTION
29.1.6.2.6. Methods
29.1.6.3. Initialization of Methods
29.1.6.3.1. Macro DEFMETHOD
29.1.6.3.2. Initialization of method metaobjects
29.1.6.4. Customization
29.1.6.4.1. Function CLOS:EXTRACT-LAMBDA-LIST
29.1.6.4.2. Function CLOS:EXTRACT-SPECIALIZER-NAMES
29.1.7. Accessor Methods
29.1.7.1. Introspection
29.1.7.1.1. Generic Function CLOS:ACCESSOR-METHOD-SLOT-DEFINITION
29.1.7.2. Customization
29.1.7.2.1. Generic Function CLOS:READER-METHOD-CLASS
29.1.7.2.2. Generic Function CLOS:WRITER-METHOD-CLASS
29.1.8. Specializers
29.1.8.1. Inheritance Structure of Specializer Metaobject Classes
29.1.8.2. Introspection
29.1.8.2.1. Function CLOS:EQL-SPECIALIZER-OBJECT
29.1.8.3. Initialization
29.1.8.3.1. Function CLOS:INTERN-EQL-SPECIALIZER
29.1.8.4. Updating Dependencies
29.1.8.4.1. Generic Function CLOS:SPECIALIZER-DIRECT-METHODS
29.1.8.4.2. Generic Function CLOS:SPECIALIZER-DIRECT-GENERIC-FUNCTIONS
29.1.8.4.3. Generic Function CLOS:ADD-DIRECT-METHOD
29.1.8.4.4. Generic Function CLOS:REMOVE-DIRECT-METHOD
29.1.9. Method Combinations
29.1.9.1. Inheritance Structure of method combination metaobject Classes
29.1.9.2. Customization
29.1.9.2.1. Generic Function CLOS:FIND-METHOD-COMBINATION
29.1.10. Slot Access
29.1.10.1. Instance Structure Protocol
29.1.10.2. Funcallable Instances
29.1.10.3. Customization
29.1.10.3.1. Function CLOS:STANDARD-INSTANCE-ACCESS
29.1.10.3.2. Function CLOS:FUNCALLABLE-STANDARD-INSTANCE-ACCESS
29.1.10.3.3. Function CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION
29.1.10.3.4. Generic Function CLOS:SLOT-VALUE-USING-CLASS
29.1.10.3.5. Generic Function (SETF CLOS:SLOT-VALUE-USING-CLASS)
29.1.10.3.6. Generic Function CLOS:SLOT-BOUNDP-USING-CLASS
29.1.10.3.7. Generic Function CLOS:SLOT-MAKUNBOUND-USING-CLASS
29.1.11. Dependent Maintenance
29.1.11.1. Protocol
29.1.11.1.1. Generic Function CLOS:UPDATE-DEPENDENT
29.1.11.1.2. Generic Function CLOS:ADD-DEPENDENT
29.1.11.1.3. Generic Function CLOS:REMOVE-DEPENDENT
29.1.11.1.4. Generic Function CLOS:MAP-DEPENDENTS
29.1.12. Deviations from [AMOP]

29.1.1. Introduction

The CLOS specification ([ANSI CL] Chanpter 7) describes the standard Programmer Interface for the Common Lisp Object System (CLOS). This document extends that specification by defining a metaobject protocol for CLOS - that is, a description of CLOS itself as an extensible CLOS program. In this description, the fundamental elements of CLOS programs (classes, slot definitions, generic functions, methods, specializers and method combinations) are represented by first-class objects. The behavior of CLOS is provided by these objects, or, more precisely, by methods specialized to the classes of these objects.

Because these objects represent pieces of CLOS programs, and because their behavior provides the behavior of the CLOS language itself, they are considered meta-level objects or metaobjects. The protocol followed by the metaobjects to provide the behavior of CLOS is called the CLOSMetaobject Protocol” (MOP).

29.1.1.1. Notation

The description of functions follows the same form as used in the CLOS specification. The description of generic functions is similar to that in the CLOS specification, but some minor changes have been made in the way methods are presented.

The following is an example of the format for the syntax description of a generic function:

(gf1 x y &OPTIONAL v &KEY k)

This description indicates that gf1 is a generic function with two required parameters, x and y, an optional parameter v and a keyword parameter k.

The description of a generic function includes a description of its behavior. This provides the general behavior, or protocol of the generic function. All methods defined on the generic function, both portable and specified, must have behavior consistent with this description.

Every generic function described here is an instance of the class STANDARD-GENERIC-FUNCTION and uses the STANDARD method combination.

The description of a generic function also includes descriptions of the specified methods for that generic function. In the description of these methods, a method signature is used to describe the parameters and parameter specializers of each method. The following is an example of the format for a method signature:

(gf1 (x CLASS) y &OPTIONAL v &KEY k)

This signature indicates that this primary method on the generic function gf1 has two required parameters, named x and y. In addition, there is an optional parameter v and a keyword parameter k. This signature also indicates that the method's parameter specializers are the classes CLASS and T.

The description of each method includes a description of the behavior particular to that method.

An abbreviated syntax is used when referring to a method defined elsewhere in the document. This abbreviated syntax includes the name of the generic function, the qualifiers, and the parameter specializers. A reference to the method with the signature shown above is written as: gf1 (CLASS T).

29.1.1.2. Package

The package exporting the Meta-Object Protocol symbols is unspecified.

Implementation dependent: only in CLISP

The symbols specified by the Meta-Object Protocol are exported from the package CLOS and EXT:RE-EXPORTed from the package EXT.

The package exporting the Meta-Object Protocol symbols is different in other implementations: In SBCL it is the package SB-MOP; in OpenMCL it is the package OPENMCL-MOP.

29.1.2. Overview

29.1.2.1. Metaobjects

For each kind of program element there is a corresponding basic metaobject class . These are the classes: CLASS, CLOS:SLOT-DEFINITION, GENERIC-FUNCTION, METHOD and METHOD-COMBINATION. A metaobject class is a subclass of exactly one of these classes. The results are undefined if an attempt is made to define a CLASS that is a subclass of more than one basic metaobject class. A metaobject is an instance of a metaobject class.

Each metaobject represents one program element. Associated with each metaobject is the information required to serve its role. This includes information that might be provided directly in a user interface macro such as DEFCLASS or DEFMETHOD. It also includes information computed indirectly from other metaobjects such as that computed from class inheritance or the full set of methods associated with a generic function.

Much of the information associated with a metaobject is in the form of connections to other metaobjects. This interconnection means that the role of a metaobject is always based on that of other metaobjects. As an introduction to this interconnected structure, this section presents a partial enumeration of the kinds of information associated with each kind of metaobject. More detailed information is presented later.

29.1.2.1.1. Classes

A class metaobject determines the structure and the default behavior of its instances. The following information is associated with class metaobjects:

  • The name, if there is one, is available as an object.
  • The direct subclasses, direct superclasses and class precedence list are available as lists of class metaobjects.
  • The slots defined directly in the class are available as a list of direct slot definition metaobjects. The slots which are accessible in instances of the class are available as a list of effective slot definition metaobjects.
  • The methods which use the class as a specializer, and the generic functions associated with those methods are available as lists of method and generic function metaobjects respectively.
  • The documentation is available as a STRING or NIL.

See also Section 29.1.3, “Classes”

29.1.2.1.2. Slot Definitions

A slot definition metaobject contains information about the definition of a slot. There are two kinds of slot definition metaobjects: A direct slot definition metaobject is used to represent the direct definition of a slot in a class. This corresponds roughly to the slot specifiers found in DEFCLASS forms. An effective slot definition metaobject is used to represent information, including inherited information, about a slot which is accessible in instances of a particular class.

Associated with each class metaobject is a list of direct slot definition metaobjects representing the slots defined directly in the class. Also associated with each class metaobject is a list of effective slot definition metaobjects representing the set of slots accessible in instances of that class.

The following information is associated with both direct and effective slot definitions metaobjects:

  • The name, allocation, and type are available as forms that could appear in a DEFCLASS form.
  • The initialization form, if there is one, is available as a form that could appear in a DEFCLASS form. The initialization form together with its lexical environment is available as a function of no arguments which, when called, returns the result of evaluating the initialization form in its lexical environment. This is called the initfunction of the slot.
  • The slot filling initialization arguments are available as a list of symbols.
  • The documentation is available as a STRING or NIL.

Certain other information is only associated with direct slot definition metaobjects. This information applies only to the direct definition of the slot in the class (it is not inherited).

  • The function names of those generic functions for which there are automatically generated reader and writer methods. This information is available as lists of function names. Any accessors specified in the DEFCLASS form are broken down into their equivalent readers and writers in the direct slot definition.

Information, including inherited information, which applies to the definition of a slot in a particular class in which it is accessible is associated only with effective slot definition metaobjects.

  • For certain slots, the location of the slot in instances of the class is available.

See also Section 29.1.4, “Slot Definitions”

29.1.2.1.3. Generic Functions

A generic function metaobject contains information about a generic function over and above the information associated with each of the generic function's methods.

  • The name is available as a function name.
  • The methods associated with the generic function are available as a list of method metaobjects.
  • The default class for this generic function's method metaobjects is available as a class metaobject.
  • The lambda list is available as a LIST.
  • The method combination is available as a method combination metaobject.
  • The argument precedence order is available as a permutation of those symbols from the lambda list which name the required arguments of the generic function.
  • The “declarations” are available as a list of declaration specifiers.

    Note

    There is a slight misnomer in the naming of functions and options in this document: Where the term “declaration” is used, actually a declaration specifier is meant.

  • The documentation is available as a STRING or NIL.

See also Section 29.1.5, “Generic Functions”

29.1.2.1.4. Methods

A method metaobject contains information about a specific METHOD.

  • The qualifiers are available as a LIST of of non-NIL atoms.
  • The lambda list is available as a LIST.
  • The specializers are available as a list of specializer metaobjects.
  • The function is available as a FUNCTION. This function can be applied to arguments and a list of next methods using APPLY or FUNCALL.
  • When the method is associated with a generic function, that generic function metaobject is available. A method can be associated with at most one generic function at a time.
  • The documentation is available as a STRING or NIL.

See also Section 29.1.6, “Methods”

29.1.2.1.5. Specializers

A specializer metaobject represents the specializers of a METHOD. class metaobjects are themselves specializer metaobjects. A special kind of specializer metaobject is used for EQL specializers.

See also Section 29.1.8, “Specializers”

29.1.2.1.6. Method Combinations

A method combination metaobject represents the information about the method combination being used by a generic function.

Note

This document does not specify the structure of method combination metaobjects.

See also Section 29.1.9, “Method Combinations”

29.1.2.2. Inheritance Structure of Metaobject Classes

Figure 29.1. Inheritance structure of metaobject classes

Inheritance structure of metaobject classes

The inheritance structure of the specified metaobject classes is shown in Table 29.1, “Direct Superclass Relationships Among The Specified Metaobject Classes”. The class of every class shown is STANDARD-CLASS except for the classes T and FUNCTION, which are instances of the class BUILT-IN-CLASS, and the classes GENERIC-FUNCTION and STANDARD-GENERIC-FUNCTION, which are instances of the class CLOS:FUNCALLABLE-STANDARD-CLASS.


Each class with a “yes” in the “Abstract” column is an abstract class and is not intended to be instantiated. The results are undefined if an attempt is made to make an instance of one of these classes with MAKE-INSTANCE.

Each class with a “yes” in the “Subclassable” column can be used as direct superclass for portable programs. It is not meaningful to subclass a class that has a “no” in this column.

Implementation dependent: only in CLISP

The class METHOD is also subclassable: It is possible to create subclasses of METHOD that do not inherit from STANDARD-METHOD.

Implementation dependent: only in CLISP and some other implementations

The class CLOS:FUNCALLABLE-STANDARD-OBJECT's class precedence list contains FUNCTION before STANDARD-OBJECT, not after STANDARD-OBJECT. This is the most transparent way to realize the [ANSI CL] requirement (see the [ANSI CL] section 4.2.2 “Type Relationships) that GENERIC-FUNCTION's class precedence list contains FUNCTION before STANDARD-OBJECT.

The classes STANDARD-CLASS, CLOS:STANDARD-DIRECT-SLOT-DEFINITION, CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION, STANDARD-METHOD, CLOS:STANDARD-READER-METHOD, CLOS:STANDARD-WRITER-METHOD and STANDARD-GENERIC-FUNCTION are called standard metaobject classes. For each kind of metaobject, this is the class the user interface macros presented in the CLOS use by default. These are also the classes on which user specializations are normally based.

The classes BUILT-IN-CLASS, CLOS:FUNCALLABLE-STANDARD-CLASS and CLOS:FORWARD-REFERENCED-CLASS are special-purpose class metaobject classes. Built-in classes are instances of the class BUILT-IN-CLASS. The class CLOS:FUNCALLABLE-STANDARD-CLASS provides a special kind of instances described in Section 29.1.10.2, “Funcallable Instances”. When the definition of a class references another class which has not yet been defined, an instance of CLOS:FORWARD-REFERENCED-CLASS is used as a stand-in until the class is actually defined.

Implementation of class CLOS:FORWARD-REFERENCED-CLASS in CLISP

The class CLOS:FORWARD-REFERENCED-CLASS is implemented in a way that fixes several flaws in the [AMOP] specification.

It is not a subclass of CLASS and CLOS:SPECIALIZER, just a subclass of CLOS:METAOBJECT, because forward references to classes are not classes and cannot be used as specializers of methods. An [AMOP] compatibility mode is provided, however, if you set the variable CUSTOM:*FORWARD-REFERENCED-CLASS-MISDESIGN* to T. In this mode, CLOS:FORWARD-REFERENCED-CLASS is formally a subclass of CLASS and CLOS:SPECIALIZER, but the behaviour of CLOS:FORWARD-REFERENCED-CLASS instances is the same.

The [AMOP] says that the first argument of CLOS:ENSURE-CLASS-USING-CLASS can be a CLOS:FORWARD-REFERENCED-CLASS. But from the description of CLOS:ENSURE-CLASS, it is clear that it can only be a class returned by FIND-CLASS, and [ANSI CL] FIND-CLASS cannot return a CLOS:FORWARD-REFERENCED-CLASS.

The [AMOP] says that CLOS:ENSURE-CLASS-USING-CLASS creates a CLOS:FORWARD-REFERENCED-CLASS for not-yet-defined class symbols among the direct-superclasses list. But this leads to many CLOS:FORWARD-REFERENCED-CLASS with the same name (since they cannot be stored and retrieved through FIND-CLASS), and since CHANGE-CLASS preserves the EQ-ness, after the class is defined, we have many class objects with the same name.

In the direct-superclasses list of non-finalized classes, CLOS:FORWARD-REFERENCED-CLASS instances can occur, denoting classes that have not yet been defined. When or after such a class gets defined, the CLOS:FORWARD-REFERENCED-CLASS instance is replaced with the real class. CLISP uses simple object replacement, not CHANGE-CLASS, in this process.

The class STANDARD-OBJECT is the default direct superclass of the class STANDARD-CLASS. When an instance of the class STANDARD-CLASS is created, and no direct superclasses are explicitly specified, it defaults to the class STANDARD-OBJECT. In this way, any behavior associated with the class STANDARD-OBJECT will be inherited, directly or indirectly, by all instances of the class STANDARD-CLASS. A subclass of STANDARD-CLASS may have a different class as its default direct superclass, but that class must be a subclass of the class STANDARD-OBJECT.

The same is true for CLOS:FUNCALLABLE-STANDARD-CLASS and CLOS:FUNCALLABLE-STANDARD-OBJECT.

The class CLOS:SPECIALIZER captures only the most basic behavior of method specializers, and is not itself intended to be instantiated. The class CLASS is a direct subclass of CLOS:SPECIALIZER reflecting the property that classes by themselves can be used as method specializers. The class CLOS:EQL-SPECIALIZER is used for EQL specializers.

29.1.2.2.1. Implementation and User Specialization

The purpose of the Metaobject Protocol is to provide users with a powerful mechanism for extending and customizing the basic behavior of the CLOS. As an object-oriented description of the basic CLOS behavior, the Metaobject Protocol makes it possible to create these extensions by defining specialized subclasses of existing metaobject classes.

The Metaobject Protocol provides this capability without interfering with the implementor's ability to develop high-performance implementations. This balance between user extensibility and implementor freedom is mediated by placing explicit restrictions on each. Some of these restrictions are general---they apply to the entire class graph and the applicability of all methods. These are presented in this section.

The following additional terminology is used to present these restrictions:

  • Metaobjects are divided into three categories. Those defined in this document are called specified; those defined by an implementation but not mentioned in this document are called implementation-specific; and those defined by a portable program are called portable.
  • A class i is interposed between two other classes k1 and k2 if and only if there is some path, following direct superclasses, from the class k1 to the class k2 which includes i.
  • A method is specialized to a class if and only if that class is in the list of specializers associated with the method; and the method is in the list of methods associated with some generic function.
  • In a given implementation, a specified method is said to have been promoted if and only if the specializers of the method, x1 ... xn, are defined in this specification as the classes k1 ... kn, but in the implementation, one or more of the specializers xl, is a superclass of the class given in the specification kl.
  • For a given generic function and set of arguments, a method k2 extends a method k1 if and only if:

    1. k1 and k2 are both associated with the given generic function
    2. k1 and k2 are both applicable to the given arguments,
    3. the specializers and qualifiers of the methods are such that when the generic function is called, k2 is executed before k1,
    4. k1 will be executed if and only if CALL-NEXT-METHOD is invoked from within the body of k2 and
    5. CALL-NEXT-METHOD is invoked from within the body of k2, thereby causing k1 to be executed.
  • For a given generic function and set of arguments, a method k2 overrides a method k1 if and only if conditions i through iv above hold and, instead of v,

    1. CALL-NEXT-METHOD is not invoked from within the body of k2, thereby preventing k1 from being executed.
29.1.2.2.1.1. Restrictions on Portable Programs

Portable programs are allowed to define subclasses of specified classes, and are permitted to define methods on specified generic functions, with the following restrictions:

  • Portable programs must not redefine any specified classes, generic functions, methods or method combinations. Any method defined by a portable program on a specified generic function must have at least one specializer that is neither a specified class nor an EQL specializer whose associated value is an instance of a specified class.
  • Portable programs may define methods that extend specified methods unless the description of the specified method explicitly prohibits this. Unless there is a specific statement to the contrary, these extending methods must return whatever value was returned by the call to CALL-NEXT-METHOD.
  • Portable programs may define methods that override specified methods only when the description of the specified method explicitly allows this. Typically, when a method is allowed to be overridden, a small number of related methods will need to be overridden as well.

    An example of this is the specified methods on the generic functions CLOS:ADD-DEPENDENT, CLOS:REMOVE-DEPENDENT and CLOS:MAP-DEPENDENTS. Overriding a specified method on one of these generic functions requires that the corresponding method on the other two generic functions be overridden as well.

  • Portable methods on specified generic functions specialized to portable metaobject classes must be defined before any instances of those classes (or any subclasses) are created, either directly or indirectly by a call to MAKE-INSTANCE. Methods can be defined after instances are created by ALLOCATE-INSTANCE however. Portable metaobject classes cannot be redefined.

    Note

    The purpose of this last restriction is to permit implementations to provide performance optimizations by analyzing, at the time the first instance of a metaobject class is initialized, what portable methods will be applicable to it. This can make it possible to optimize calls to those specified generic functions which would have no applicable portable methods.

    Implementation dependent: only in CLISP

    When a metaobject class is redefined, CLISP issues a WARNING that the redefinition has no effect. To avoid this warning, place all metaobject class definitions in a separate file, compile it in a separate session (because DEFCLASS in CLISP is evaluated at compile time too; see Section 29.1.2.3.2, “Compile-file Processing of Specific User Interface Macros”), and then LOAD it only once per session.

The results are undefined if any of these restrictions are violated.

Note

The specification technology used in this document needs further development. The concepts of object-oriented protocols and subclass specialization are intuitively familiar to programmers of object-oriented systems; the protocols presented here fit quite naturally into this framework. Nonetheless, in preparing this document, we have found it difficult to give specification-quality descriptions of the protocols in a way that makes it clear what extensions users can and cannot write. Object-oriented protocol specification is inherently about specifying leeway, and this seems difficult using current technology.

29.1.2.2.1.2. Restrictions on Implementations

Implementations are allowed latitude to modify the structure of specified classes and methods. This includes: the interposition of implementation-specific classes; the promotion of specified methods; and the consolidation of two or more specified methods into a single method specialized to interposed classes.

Any such modifications are permitted only so long as for any portable class k that is a subclass of one or more specified classes k1 ... kn, the following conditions are met:

  • In the actual class precedence list of k, the classes k1 ... kn must appear in the same order as they would have if no implementation-specific modifications had been made.
  • The method applicability of any specified generic function must be the same in terms of behavior as it would have been had no implementation-specific changes been made. This includes specified generic functions that have had portable methods added. In this context, the expression “the same in terms of behavior” means that methods with the same behavior as those specified are applicable, and in the same order.
  • No portable class k may inherit, by virtue of being a direct or indirect subclass of a specified class, any slot for which the name is a symbol accessible in the COMMON-LISP-USER package or exported by any package defined in the [ANSI CL].
  • Implementations are free to define implementation-specific before- and after-methods on specified generic functions. Implementations are also free to define implementation-specific around-methods with extending behavior.

29.1.2.3. Processing of the User Interface Macros

A list in which the first element is one of the symbols DEFCLASS, DEFMETHOD, DEFGENERIC, DEFINE-METHOD-COMBINATION, CLOS:GENERIC-FUNCTION, CLOS:GENERIC-FLET or CLOS:GENERIC-LABELS, and which has proper syntax for that macro is called a user interface macro form. This document provides an extended specification of the DEFCLASS, DEFMETHOD and DEFGENERIC macros.

The user interface macros DEFCLASS, DEFGENERIC and DEFMETHOD can be used not only to define metaobjects that are instances of the corresponding standard metaobject class, but also to define metaobjects that are instances of appropriate portable metaobject classes. To make it possible for portable metaobject classes to properly process the information appearing in the macro form, this document provides a limited specification of the processing of these macro forms.

User interface macro forms can be evaluated or compiled and later executed. The effect of evaluating or executing a user interface macro form is specified in terms of calls to specified functions and generic functions which provide the actual behavior of the macro. The arguments received by these functions and generic functions are derived in a specified way from the macro form.

Converting a user interface macro form into the arguments to the appropriate functions and generic functions has two major aspects: the conversion of the macro argument syntax into a form more suitable for later processing, and the processing of macro arguments which are forms to be evaluated (including method bodies).

In the syntax of the DEFCLASS macro, the initform and default-initarg-initial-value-form arguments are forms which will be evaluated one or more times after the macro form is evaluated or executed. Special processing must be done on these arguments to ensure that the lexical scope of the forms is captured properly. This is done by building a function of zero arguments which, when called, returns the result of evaluating the form in the proper lexical environment.

In the syntax of the DEFMETHOD macro the forms argument is a list of forms that comprise the body of the method definition. This list of forms must be processed specially to capture the lexical scope of the macro form. In addition, the lexical functions available only in the body of methods must be introduced. To allow this and any other special processing (such as slot access optimization), a specializable protocol is used for processing the body of methods. This is discussed in Section 29.1.6.3.1.1, “Processing Method Bodies”.

29.1.2.3.1. Compile-file Processing of the User Interface Macros

It is a common practice for Common Lisp compilers, while processing a file or set of files, to maintain information about the definitions that have been compiled so far. Among other things, this makes it possible to ensure that a global macro definition (DEFMACRO form) which appears in a file will affect uses of the macro later in that file. This information about the state of the compilation is called the COMPILE-FILE environment.

When compiling files containing CLOS definitions, it is useful to maintain certain additional information in the COMPILE-FILE environment. This can make it possible to issue various kinds of warnings (e.g., lambda list congruence) and to do various performance optimizations that would not otherwise be possible.

At this time, there is such significant variance in the way existing Common Lisp implementations handle COMPILE-FILE environments that it would be premature to specify this mechanism. Consequently, this document specifies only the behavior of evaluating or executing user interface macro forms. What functions and generic functions are called during COMPILE-FILE processing of a user interface macro form is not specified. Implementations are free to define and document their own behavior. Users may need to check implementation-specific behavior before attempting to compile certain portable programs.

29.1.2.3.2. Compile-file Processing of Specific User Interface Macros
DEFCLASS

Section 29.1.3.1, “Macro DEFCLASS

Implementation dependent: only in CLISP

CLISP evaluates DEFCLASS forms also at compile time.

DEFMETHOD

Section 29.1.6.3.1, “Macro DEFMETHOD

Implementation dependent: only in CLISP

CLISP does not evaluate DEFMETHOD forms at compile time except as necessary for signature checking.

DEFGENERIC

Section 29.1.5.3.1, “Macro DEFGENERIC

Implementation dependent: only in CLISP

CLISP does not evaluate DEFGENERIC forms at compile time except as necessary for signature checking.

29.1.2.4. Metaobject Initialization Protocol

Like other objects, metaobjects can be created by calling MAKE-INSTANCE. The initialization arguments passed to MAKE-INSTANCE are used to initialize the metaobject in the usual way. The set of legal initialization arguments, and their interpretation, depends on the kind of metaobject being created. Implementations and portable programs are free to extend the set of legal initialization arguments. Detailed information about the initialization of each kind of metaobject are provided in the appropriate sections:

29.1.3. Classes

29.1.3.1. Macro DEFCLASS
29.1.3.2. Inheritance Structure of class metaobject Classes
29.1.3.3. Introspection: Readers for class metaobjects
29.1.3.3.1. Generic Function CLASS-NAME
29.1.3.3.2. Generic Function CLOS:CLASS-DIRECT-SUPERCLASSES
29.1.3.3.3. Generic Function CLOS:CLASS-DIRECT-SLOTS
29.1.3.3.4. Generic Function CLOS:CLASS-DIRECT-DEFAULT-INITARGS
29.1.3.3.5. Generic Function CLOS:CLASS-PRECEDENCE-LIST
29.1.3.3.6. Generic Function CLOS:CLASS-DIRECT-SUBCLASSES
29.1.3.3.7. Generic Function CLOS:CLASS-SLOTS
29.1.3.3.8. Generic Function CLOS:CLASS-DEFAULT-INITARGS
29.1.3.3.9. Generic Function CLOS:CLASS-FINALIZED-P
29.1.3.3.10. Generic Function CLOS:CLASS-PROTOTYPE
29.1.3.3.11. Methods
29.1.3.4. Class Finalization Protocol
29.1.3.5. Class Initialization
29.1.3.5.1. Initialization of class metaobjects
29.1.3.5.1.1. Methods
29.1.3.5.1.2. Initialization of Anonymous Classes
29.1.3.5.2. Reinitialization of class metaobjects
29.1.3.6. Customization
29.1.3.6.1. Generic Function (SETF CLASS-NAME)
29.1.3.6.2. Generic Function CLOS:ENSURE-CLASS
29.1.3.6.3. Generic Function CLOS:ENSURE-CLASS-USING-CLASS
29.1.3.6.4. Generic Function CLOS:FINALIZE-INHERITANCE
29.1.3.6.5. Generic Function MAKE-INSTANCE
29.1.3.6.6. Generic Function ALLOCATE-INSTANCE
29.1.3.6.7. Generic Function CLOS:VALIDATE-SUPERCLASS
29.1.3.6.8. Generic Function CLOS:COMPUTE-DIRECT-SLOT-DEFINITION-INITARGS
29.1.3.6.9. Generic Function CLOS:DIRECT-SLOT-DEFINITION-CLASS
29.1.3.6.10. Generic Function CLOS:COMPUTE-CLASS-PRECEDENCE-LIST
29.1.3.6.11. Generic Function CLOS:COMPUTE-SLOTS
29.1.3.6.12. Generic Function CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION
29.1.3.6.13. Generic Function CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS
29.1.3.6.14. Generic Function CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS
29.1.3.6.15. Generic Function CLOS:COMPUTE-DEFAULT-INITARGS
29.1.3.7. Updating Dependencies
29.1.3.7.1. Generic Function CLOS:ADD-DIRECT-SUBCLASS
29.1.3.7.2. Generic Function CLOS:REMOVE-DIRECT-SUBCLASS

29.1.3.1. Macro DEFCLASS

The evaluation or execution of a DEFCLASS form results in a call to the CLOS:ENSURE-CLASS function. The arguments received by CLOS:ENSURE-CLASS are derived from the DEFCLASS form in a defined way. The exact macro-expansion of the DEFCLASS form is not defined, only the relationship between the arguments to the DEFCLASS macro and the arguments received by the CLOS:ENSURE-CLASS function. Examples of typical DEFCLASS forms and sample expansions are shown in the following two examples:

A DEFCLASS form with standard slot and class options and an expansion of it that would result in the proper call to CLOS:ENSURE-CLASS.

(defclass plane (moving-object graphics-object)
  ((altitude :initform 0 :accessor plane-altitude)
   (speed))
  (:default-initargs :engine *jet*))

(ensure-class 'plane
  ':direct-superclasses '(moving-object graphics-object)
  ':direct-slots (list (list ':name 'altitude
                             ':initform '0
                             ':initfunction #'(lambda () 0)
                             ':readers '(plane-altitude)
                             ':writers '((setf plane-altitude)))
                       (list ':name 'speed))
  ':direct-default-initargs (list (list ':engine
                                        '*jet*
                                        #'(lambda () *jet*))))

A DEFCLASS form with non-standard class and slot options, and an expansion of it which results in the proper call to CLOS:ENSURE-CLASS. Note that the order of the slot options has not affected the order of the properties in the canonicalized slot specification, but has affected the order of the elements in the lists which are the values of those properties.

(defclass sst (plane)
  ((mach mag-step 2
         locator sst-mach
         locator mach-location
         :reader mach-speed
         :reader mach))
  (:metaclass faster-class)
  (another-option foo bar))

(ensure-class 'sst
  ':direct-superclasses '(plane)
  ':direct-slots (list (list ':name 'mach
                             ':readers '(mach-speed mach)
                             'mag-step '2
                             'locator '(sst-mach mach-location)))
  ':metaclass 'faster-class
  'another-option '(foo bar))
  • The name argument to DEFCLASS becomes the value of the first argument to CLOS:ENSURE-CLASS. This is the only positional argument accepted by CLOS:ENSURE-CLASS; all other arguments are keyword arguments.
  • The :DIRECT-SUPERCLASSES argument to DEFCLASS becomes the value of the :DIRECT-SUPERCLASSES keyword argument to CLOS:ENSURE-CLASS.
  • The :DIRECT-SLOTS argument to DEFCLASS becomes the value of the :DIRECT-SLOTS keyword argument to CLOS:ENSURE-CLASS. Special processing of this value is done to regularize the form of each slot specification and to properly capture the lexical scope of the initialization forms. This is done by converting each slot specification to a property list called a canonicalized slot specification. The resulting list of canonicalized slot specifications is the value of the :DIRECT-SLOTS keyword argument.

    Canonicalized slot specifications are later used as the keyword arguments to a generic function which will, in turn, pass them to MAKE-INSTANCE for use as a set of initialization arguments. Each canonicalized slot specification is formed from the corresponding slot specification as follows:

    • The name of the slot is the value of the :NAME property. This property appears in every canonicalized slot specification.
    • When the :INITFORM slot option is present in the slot specification, then both the :INITFORM and :INITFUNCTION properties are present in the canonicalized slot specification. The value of the :INITFORM property is the initialization form. The value of the :INITFUNCTION property is a function of zero arguments which, when called, returns the result of evaluating the initialization form in its proper lexical environment.
    • If the :INITFORM slot option is not present in the slot specification, then either the :INITFUNCTION property will not appear, or its value will be false. In such cases, the value of the :INITFORM property, or whether it appears, is unspecified.
    • The value of the :INITARGS property is a list of the values of each :INITARG slot option. If there are no :INITARG slot options, then either the :INITARGS property will not appear or its value will be the empty list.
    • The value of the :READERS property is a list of the values of each :READER and :ACCESSOR slot option. If there are no :READER or :ACCESSOR slot options, then either the :READERS property will not appear or its value will be the empty list.
    • The value of the :WRITERS property is a list of the values specified by each :WRITER and :ACCESSOR slot option. The value specified by a :WRITER slot option is just the value of the slot option. The value specified by an :ACCESSOR slot option is a two element list: the first element is the symbol SETF, the second element is the value of the slot option. If there are no :WRITER or :ACCESSOR slot options, then either the :WRITERS property will not appear or its value will be the empty list.
    • The value of the :DOCUMENTATION property is the value of the :DOCUMENTATION slot option. If there is no :DOCUMENTATION slot option, then either the :DOCUMENTATION property will not appear or its value will be false.
    • All other slot options appear as the values of properties with the same name as the slot option. Note that this includes not only the remaining standard slot options (:ALLOCATION and :TYPE), but also any other options and values appearing in the slot specification. If one of these slot options appears more than once, the value of the property will be a list of the specified values.
    • An implementation is free to add additional properties to the canonicalized slot specification provided these are not symbols accessible in the COMMON-LISP-USER package, or exported by any package defined in the [ANSI CL].
  • The default initargs class option, if it is present in the DEFCLASS form, becomes the value of the :DIRECT-DEFAULT-INITARGS keyword argument to CLOS:ENSURE-CLASS. Special processing of this value is done to properly capture the lexical scope of the default value forms. This is done by converting each default initarg in the class option into a canonicalized default initialization argument. The resulting list of canonicalized default initialization arguments is the value of the :DIRECT-DEFAULT-INITARGS keyword argument to CLOS:ENSURE-CLASS.

    A canonicalized default initarg is a list of three elements. The first element is the name; the second is the actual form itself; and the third is a function of zero arguments which, when called, returns the result of evaluating the default value form in its proper lexical environment.

    Implementation dependent: only in CLISP

    If a default initargs class option is not present in the DEFCLASS form, :DIRECT-DEFAULT-INITARGS NIL is passed to CLOS:ENSURE-CLASS.

    This is needed to fulfill the [ANSI CL] requirement (see Section 4.6, “Redefining Classes [CLHS-4.3.6]”) that the resulting CLASS object reflects the DEFCLASS form.

  • The metaclass class option, if it is present in the DEFCLASS form, becomes the value of the :METACLASS keyword argument to CLOS:ENSURE-CLASS.

    Implementation dependent: only in CLISP

    If a metaclass class option is not present in the DEFCLASS form, :METACLASS STANDARD-CLASS is passed to CLOS:ENSURE-CLASS.

    This is needed to fulfill the [ANSI CL] requirement (see Section 4.6, “Redefining Classes [CLHS-4.3.6]”) that the resulting CLASS object reflects the DEFCLASS form.

  • The documentation class option, if it is present in the DEFCLASS form, becomes the value of the :DOCUMENTATION keyword argument to CLOS:ENSURE-CLASS.

    Implementation dependent: only in CLISP

    If a documentation class option is not present in the DEFCLASS form, :DIRECT-DEFAULT-INITARGS NIL is passed to CLOS:ENSURE-CLASS.

    This is needed to fulfill the [ANSI CL] requirement (see Section 4.6, “Redefining Classes [CLHS-4.3.6]”) that the resulting CLASS object reflects the DEFCLASS form.

  • Any other class options become the value of keyword arguments with the same name. The value of the keyword argument is the tail of the class option. An ERROR is SIGNALed if any class option appears more than once in the DEFCLASS form.

    Implementation dependent: only in CLISP

    The default initargs of the metaclass are added at the end of the list of arguments to pass to CLOS:ENSURE-CLASS.

    This is needed to fulfill the [ANSI CL] requirement (see Section 4.6, “Redefining Classes [CLHS-4.3.6]”) that the resulting CLASS object reflects the DEFCLASS form.

In the call to CLOS:ENSURE-CLASS, every element of its arguments appears in the same left-to-right order as the corresponding element of the DEFCLASS form, except that the order of the properties of canonicalized slot specifications is unspecified. The values of properties in canonicalized slot specifications do follow this ordering requirement. Other ordering relationships in the keyword arguments to CLOS:ENSURE-CLASS are unspecified.

The result of the call to CLOS:ENSURE-CLASS is returned as the result of evaluating or executing the DEFCLASS form.

29.1.3.2. Inheritance Structure of class metaobject Classes

Figure 29.2. Inheritance structure of class metaobject classes

Inheritance structure of class metaobject classes

29.1.3.3. Introspection: Readers for class metaobjects

In this and the following sections, the “reader” generic functions which simply return information associated with a particular kind of metaobject are presented together. General information is presented first, followed by a description of the purpose of each, and ending with the specified methods for these generic functions.

The reader generic functions which simply return information associated with class metaobjects are presented together in this section.

Each of the reader generic functions for class metaobjects has the same syntax, accepting one required argument called class, which must be a class metaobject; otherwise, an ERROR is SIGNALed. An ERROR is also SIGNALed if the class metaobject has not been initialized.

These generic functions can be called by the user or the implementation.

For any of these generic functions which returns a list, such lists will not be mutated by the implementation. The results are undefined if a portable program allows such a list to be mutated.

29.1.3.3.1. Generic Function CLASS-NAME
(CLASS-NAME class)

Returns the name of class. This value can be any Lisp object, but is usually a symbol, or NIL if the class has no name. This is the defaulted value of the :NAME initialization argument that was associated with the class during initialization or reinitialization. (Also see (SETF CLASS-NAME).)

Returns a list of the direct superclasses of class. The elements of this list are class metaobjects. The empty list is returned if class has no direct superclasses. This is the defaulted value of the :DIRECT-SUPERCLASSES initialization argument that was associated with the class during initialization or reinitialization.

Implementation dependent: only in CLISP

For a class that has not yet been finalized, the returned list may contain CLOS:FORWARD-REFERENCED-CLASS instances as placeholder for classes that were not yet defined when finalization of the class was last attempted.

29.1.3.3.3. Generic Function CLOS:CLASS-DIRECT-SLOTS

Returns a set of the direct slots of class. The elements of this set are direct slot definition metaobjects. If the class has no direct slots, the empty set is returned. This is the defaulted value of the :DIRECT-SLOTS initialization argument that was associated with the class during initialization and reinitialization.

Returns a list of the direct default initialization arguments for class. Each element of this list is a canonicalized default initialization argument. The empty list is returned if class has no direct default initialization arguments. This is the defaulted value of the :DIRECT-DEFAULT-INITARGS initialization argument that was associated with the class during initialization or reinitialization.

29.1.3.3.5. Generic Function CLOS:CLASS-PRECEDENCE-LIST

Returns the class precedence list of class. The elements of this list are class metaobjects.

During class finalization CLOS:FINALIZE-INHERITANCE calls CLOS:COMPUTE-CLASS-PRECEDENCE-LIST to compute the class precedence list of the class. That value is associated with the class metaobject and is returned by CLOS:CLASS-PRECEDENCE-LIST.

This generic function SIGNALs an ERROR if class has not been finalized.

29.1.3.3.6. Generic Function CLOS:CLASS-DIRECT-SUBCLASSES

Returns a set of the direct subclasses of class. The elements of this set are class metaobjects that all mention this class among their direct superclasses. The empty set is returned if class has no direct subclasses. This value is maintained by the generic functions CLOS:ADD-DIRECT-SUBCLASS and CLOS:REMOVE-DIRECT-SUBCLASS.

Implementation dependent: only in CLISP

The set of direct subclasses of a class is internally managed as a EXT:WEAK-LIST. Therefore the existence of the CLOS:CLASS-DIRECT-SUBCLASSES function does not prevent otherwise unreferenced classes from being garbage-collected.

29.1.3.3.7. Generic Function CLOS:CLASS-SLOTS

Returns a possibly empty set of the slots accessible in instances of class. The elements of this set are effective slot definition metaobjects.

During class finalization CLOS:FINALIZE-INHERITANCE calls CLOS:COMPUTE-SLOTS to compute the slots of the class. That value is associated with the class metaobject and is returned by CLOS:CLASS-SLOTS.

This generic function SIGNALs an ERROR if class has not been finalized.

29.1.3.3.8. Generic Function CLOS:CLASS-DEFAULT-INITARGS

Returns a list of the default initialization arguments for class. Each element of this list is a canonicalized default initialization argument. The empty list is returned if class has no default initialization arguments.

During finalization CLOS:FINALIZE-INHERITANCE calls CLOS:COMPUTE-DEFAULT-INITARGS to compute the default initialization arguments for the class. That value is associated with the class metaobject and is returned by CLOS:CLASS-DEFAULT-INITARGS.

This generic function SIGNALs an ERROR if class has not been finalized.

29.1.3.3.9. Generic Function CLOS:CLASS-FINALIZED-P

Returns true if class has been finalized. Returns false otherwise. Also returns false if the class has not been initialized.

29.1.3.3.10. Generic Function CLOS:CLASS-PROTOTYPE

Returns a prototype instance of class. Whether the instance is initialized is not specified. The results are undefined if a portable program modifies the binding of any slot of a prototype instance.

This generic function SIGNALs an ERROR if class has not been finalized.

This allows non-consing[3] access to slots with allocation :CLASS:

(defclass counter ()
  ((count :allocation :class :initform 0 :reader how-many)))
(defmethod initialize-instance :after ((obj counter) &rest args)
  (incf (slot-value obj 'count)))
(defclass counted-object (counter) ((name :initarg :name)))
 

Now one can find out how many COUNTED-OBJECTs have been created by using (HOW-MANY (CLOS:CLASS-PROTOTYPE (FIND-CLASS 'COUNTER))):

(MAKE-INSTANCE 'counted-object :name 'foo)
⇒ #<COUNTED-OBJECT #x203028C9>
(HOW-MANY (CLOS:CLASS-PROTOTYPE (FIND-CLASS 'counter)))
⇒ 1
(MAKE-INSTANCE 'counted-object :name 'bar)
⇒ #<COUNTED-OBJECT #x20306CB1>
(HOW-MANY (CLOS:CLASS-PROTOTYPE (FIND-CLASS 'counter)))
⇒ 2
29.1.3.3.11. Methods

The specified methods for the class metaobject reader generic functions are presented below.

Each entry in the table indicates a method on one of the reader generic functions, specialized to a specified class. The number in each entry is a reference to the full description of the method. The full descriptions appear after the table.

Class Reader Methods

  1. This method returns the value which was associated with the class metaobject during initialization or reinitialization.
  2. This method returns the value associated with the class metaobject by CLOS:FINALIZE-INHERITANCE (STANDARD-CLASS) or CLOS:FINALIZE-INHERITANCE (CLOS:FUNCALLABLE-STANDARD-CLASS)
  3. This method SIGNALs an ERROR.
  4. This method returns the empty list.
  5. This method returns true.
  6. This method returns false.
  7. This method returns a value derived from the information in Table 29.1, “Direct Superclass Relationships Among The Specified Metaobject Classes”, except that implementation-specific modifications are permitted as described in Section 29.1.2.2.1, “Implementation and User Specialization”.
  8. This method returns the name of the built-in class.
  9. This methods returns a value which is maintained by CLOS:ADD-DIRECT-SUBCLASS(CLASS CLASS) and CLOS:REMOVE-DIRECT-SUBCLASS (CLASS CLASS). This method can be overridden only if those methods are overridden as well.
  10. No behavior is specified for this method beyond that which is specified for the generic function.

29.1.3.4. Class Finalization Protocol

Class finalization is the process of computing the information a class inherits from its superclasses and preparing to actually allocate instances of the class. The class finalization process includes computing the class's class precedence list, the full set of slots accessible in instances of the class and the full set of default initialization arguments for the class. These values are associated with the class metaobject and can be accessed by calling the appropriate reader. In addition, the class finalization process makes decisions about how instances of the class will be implemented.

To support forward-referenced superclasses, and to account for the fact that not all classes are actually instantiated, class finalization is not done as part of the initialization of the class metaobject. Instead, finalization is done as a separate protocol, invoked by calling the generic function CLOS:FINALIZE-INHERITANCE. The exact point at which CLOS:FINALIZE-INHERITANCE is called depends on the class of the class metaobject; for STANDARD-CLASS it is called sometime after all the classes superclasses are defined, but no later than when the first instance of the class is allocated (by ALLOCATE-INSTANCE).

The first step of class finalization is computing the class precedence list. Doing this first allows subsequent steps to access the class precedence list. This step is performed by calling the generic function CLOS:COMPUTE-CLASS-PRECEDENCE-LIST. The value returned from this call is associated with the class metaobject and can be accessed by calling the CLOS:CLASS-PRECEDENCE-LIST generic function.

The second step is computing the full set of slots that will be accessible in instances of the class. This step is performed by calling the generic function CLOS:COMPUTE-SLOTS. The result of this call is a list of effective slot definition metaobjects. This value is associated with the class metaobject and can be accessed by calling the CLOS:CLASS-SLOTS generic function.

The behavior of CLOS:COMPUTE-SLOTS is itself layered, consisting of calls to CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS and CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION.

The final step of class finalization is computing the full set of initialization arguments for the class. This is done by calling the generic function CLOS:COMPUTE-DEFAULT-INITARGS. The value returned by this generic function is associated with the class metaobject and can be accessed by calling CLOS:CLASS-DEFAULT-INITARGS.

If the class was previously finalized, CLOS:FINALIZE-INHERITANCE may call MAKE-INSTANCES-OBSOLETE. The circumstances under which this happens are described in the [ANSI CL] section Section 4.6, “Redefining Classes [CLHS-4.3.6]”.

Forward-referenced classes, which provide a temporary definition for a class which has been referenced but not yet defined, can never be finalized. An ERROR is SIGNALed if CLOS:FINALIZE-INHERITANCE is called on a forward-referenced class.

29.1.3.5. Class Initialization

29.1.3.5.1. Initialization of class metaobjects

A class metaobject can be created by calling MAKE-INSTANCE. The initialization arguments establish the definition of the class. A class metaobject can be redefined by calling REINITIALIZE-INSTANCE. Some classes of class metaobject do not support redefinition; in these cases, REINITIALIZE-INSTANCE SIGNALs an ERROR.

Initialization of a class metaobject must be done by calling MAKE-INSTANCE and allowing it to call INITIALIZE-INSTANCE. Reinitialization of a class metaobject must be done by calling REINITIALIZE-INSTANCE. Portable programs must not

Since metaobject classes may not be redefined, no behavior is specified for the result of calls to UPDATE-INSTANCE-FOR-REDEFINED-CLASS on class metaobjects. Since the class of class metaobjects may not be changed, no behavior is specified for the result of calls to UPDATE-INSTANCE-FOR-DIFFERENT-CLASS on class metaobjects.

During initialization or reinitialization, each initialization argument is checked for errors and then associated with the class metaobject. The value can then be accessed by calling the appropriate accessor as shown in Table 29.2, “Initialization arguments and accessors for class metaobjects”.

This section begins with a description of the error checking and processing of each initialization argument. This is followed by a table showing the generic functions that can be used to access the stored initialization arguments. Initialization behavior specific to the different specified class metaobject classes comes next. The section ends with a set of restrictions on portable methods affecting class metaobject initialization and reinitialization.

In these descriptions, the phrase “this argument defaults to value” means that when that initialization argument is not supplied, initialization or reinitialization is performed as if value had been supplied. For some initialization arguments this could be done by the use of default initialization arguments, but whether it is done this way is not specified. Implementations are free to define default initialization arguments for specified class metaobject classes. Portable programs are free to define default initialization arguments for portable subclasses of the class CLASS.

Unless there is a specific note to the contrary, then during reinitialization, if an initialization argument is not supplied, the previously stored value is left unchanged.

After the processing and defaulting of initialization arguments described above, the value of each initialization argument is associated with the class metaobject. These values can then be accessed by calling the corresponding generic function. The correspondences are as follows:

Table 29.2. Initialization arguments and accessors for class metaobjects

Initialization ArgumentGeneric Function
:DIRECT-DEFAULT-INITARGSCLOS:CLASS-DIRECT-DEFAULT-INITARGS
:DIRECT-SLOTSCLOS:CLASS-DIRECT-SLOTS
:DIRECT-SUPERCLASSESCLOS:CLASS-DIRECT-SUPERCLASSES
:DOCUMENTATIONDOCUMENTATION
:NAMECLASS-NAME


Instances of the class STANDARD-CLASS support multiple inheritance and reinitialization. Instances of the class CLOS:FUNCALLABLE-STANDARD-CLASS support multiple inheritance and reinitialization. For forward referenced classes, all of the initialization arguments default to NIL.

Implementation dependent: only in CLISP

Instances of the class STRUCTURE-CLASS do not support multiple inheritance and reinitialization.

Since built-in classes cannot be created or reinitialized by the user, an ERROR is SIGNALed if INITIALIZE-INSTANCE or REINITIALIZE-INSTANCE are called to initialize or reinitialize a derived instance of the class BUILT-IN-CLASS.

29.1.3.5.1.1. Methods

It is not specified which methods provide the initialization and reinitialization behavior described above. Instead, the information needed to allow portable programs to specialize this behavior is presented as a set of restrictions on the methods a portable program can define. The model is that portable initialization methods have access to the class metaobject when either all or none of the specified initialization has taken effect.

These restrictions govern the methods that a portable program can define on the generic functions INITIALIZE-INSTANCE, REINITIALIZE-INSTANCE, and SHARED-INITIALIZE. These restrictions apply only to methods on these generic functions for which the first specializer is a subclass of the class CLASS. Other portable methods on these generic functions are not affected by these restrictions.

  • Portable programs must not define methods on SHARED-INITIALIZE.
  • For INITIALIZE-INSTANCE and REINITIALIZE-INSTANCE:

    • Portable programs must not define primary methods.
    • Portable programs may define around-methods, but these must be extending, not overriding methods.
    • Portable before-methods must assume that when they are run, none of the initialization behavior described above has been completed.
    • Portable after-methods must assume that when they are run, all of the initialization behavior described above has been completed.

The results are undefined if any of these restrictions are violated.

29.1.3.5.1.2. Initialization of Anonymous Classes

class metaobjects created with MAKE-INSTANCE are usually anonymous; that is, they have no proper name. An anonymous class metaobject can be given a proper name using (SETF FIND-CLASS) and (SETF CLASS-NAME).

When a class metaobject is created with MAKE-INSTANCE, it is initialized in the usual way. The initialization arguments passed to MAKE-INSTANCE are use to establish the definition of the class. Each initialization argument is checked for errors and associated with the class metaobject. The initialization arguments correspond roughly to the arguments accepted by the DEFCLASS macro, and more closely to the arguments accepted by the CLOS:ENSURE-CLASS function.

Some class metaobject classes allow their instances to be redefined. When permissible, this is done by calling REINITIALIZE-INSTANCE. This is discussed in the next section.

An example of creating an anonymous class directly using MAKE-INSTANCE follows:

(flet ((zero () 0)
       (propellor () *propellor*))
  (make-instance 'standard-class
    :name '(my-class foo)
    :direct-superclasses (list (find-class 'plane)
                               another-anonymous-class)
    :direct-slots `((:name x
                     :initform 0
                     :initfunction ,#'zero
                     :initargs (:x)
                     :readers (position-x)
                     :writers ((setf position-x)))
                    (:name y
                     :initform 0
                     :initfunction ,#'zero
                     :initargs (:y)
                     :readers (position-y)
                     :writers ((setf position-y))))
    :direct-default-initargs `((:engine *propellor* ,#'propellor))))
29.1.3.5.2. Reinitialization of class metaobjects

Some class metaobject classes allow their instances to be reinitialized. This is done by calling REINITIALIZE-INSTANCE. The initialization arguments have the same interpretation as in class initialization.

If the class metaobject was finalized before the call to REINITIALIZE-INSTANCE, CLOS:FINALIZE-INHERITANCE will be called again once all the initialization arguments have been processed and associated with the class metaobject. In addition, once finalization is complete, any dependents of the class metaobject will be updated by calling CLOS:UPDATE-DEPENDENT.

29.1.3.6. Customization

29.1.3.6.1. Generic Function (SETF CLASS-NAME)
Syntax
((SETF CLASS-NAME) new-name class)
Arguments
class
a class metaobject.
new-name
any Lisp object.
Values
This function returns its new-name argument.
Purpose

This function changes the name of class to new-name. This value is usually a symbol, or NIL if the class has no name.

This function works by calling REINITIALIZE-INSTANCE with class as its first argument, the symbol :NAME as its second argument and new-name as its third argument.

29.1.3.6.2. Generic Function CLOS:ENSURE-CLASS
Syntax
(CLOS:ENSURE-CLASS name &KEY &ALLOW-OTHER-KEYS)
Arguments
name
a SYMBOL.
keyword arguments
Some of the keyword arguments accepted by this function are actually processed by CLOS:ENSURE-CLASS-USING-CLASS, others are processed during initialization of the class metaobject (as described in Section 29.1.3.5.1, “Initialization of class metaobjects”).
Values
The result is a class metaobject.
Purpose

This function is called to define or redefine a class with the specified name, and can be called by the user or the implementation. It is the functional equivalent of DEFCLASS, and is called by the expansion of the DEFCLASS macro.

The behavior of this function is actually implemented by the generic function CLOS:ENSURE-CLASS-USING-CLASS. When CLOS:ENSURE-CLASS is called, it immediately calls CLOS:ENSURE-CLASS-USING-CLASS and returns that result as its own.

The first argument to CLOS:ENSURE-CLASS-USING-CLASS is computed as follows:

  • If name names a class (FIND-CLASS returns a class when called with name) use that class.
  • Otherwise use NIL.

The second argument is name. The remaining arguments are the complete set of keyword arguments received by the CLOS:ENSURE-CLASS function.

29.1.3.6.3. Generic Function CLOS:ENSURE-CLASS-USING-CLASS
Syntax
(CLOS:ENSURE-CLASS-USING-CLASS class name &KEY :DIRECT-DEFAULT-INITARGS :DIRECT-SLOTS :DIRECT-SUPERCLASSES :NAME :METACLASS &ALLOW-OTHER-KEYS)
Arguments
class
a class metaobject or NIL.
name
a class name.
:METACLASS
a class metaobject class or a class metaobject class name. If this argument is not supplied, it defaults to the class named STANDARD-CLASS. If a class name is supplied, it is interpreted as the class with that name. If a class name is supplied, but there is no such class, an ERROR is SIGNALed.
:DIRECT-SUPERCLASSES
a list of which each element is a class metaobject or a class name. An ERROR is SIGNALed if this argument is not a proper list.
additional keyword arguments
See Section 29.1.3.5.1, “Initialization of class metaobjects”
Values
The result is a class metaobject.
Purpose

This generic function is called to define or modify the definition of a named class. It is called by the CLOS:ENSURE-CLASS function. It can also be called directly.

The first step performed by this generic function is to compute the set of initialization arguments which will be used to create or reinitialize the named class. The initialization arguments are computed from the full set of keyword arguments received by this generic function as follows:

If the class argument is NIL, a new class metaobject is created by calling the MAKE-INSTANCE generic function with the value of the :METACLASS argument as its first argument, and the previously computed initialization arguments. The proper name of the newly created class metaobject is set to name. The newly created class metaobject is returned.

If the class argument is a forward referenced class, CHANGE-CLASS is called to change its class to the value specified by the :METACLASS argument. The class metaobject is then reinitialized with the previously initialization arguments. (This is a documented violation of the general constraint that CHANGE-CLASS may not be used with class metaobjects.)

Implementation dependent: only in CLISP

The class argument cannot be a forward referenced class. See Implementation of class CLOS:FORWARD-REFERENCED-CLASS in CLISP.

If the class of the class argument is not the same as the class specified by the :METACLASS argument, an ERROR is SIGNALed.

Otherwise, the class metaobject class is redefined by calling the REINITIALIZE-INSTANCE generic function with class and the initialization arguments. The class argument is then returned.

Methods

(CLOS:ENSURE-CLASS-USING-CLASS (class CLASS) name &KEY :METACLASS :DIRECT-SUPERCLASSES &ALLOW-OTHER-KEYS)

This method implements the behavior of the generic function in the case where the class argument is a class.

This method can be overridden.

(CLOS:ENSURE-CLASS-USING-CLASS (class CLOS:FORWARD-REFERENCED-CLASS) name &KEY :METACLASS :DIRECT-SUPERCLASSES &ALLOW-OTHER-KEYS)

This method implements the behavior of the generic function in the case where the class argument is a forward referenced class.

Implementation dependent: only in CLISP

This method does not exist. See Implementation of class CLOS:FORWARD-REFERENCED-CLASS in CLISP. Use the method specialized on NULL instead.

(CLOS:ENSURE-CLASS-USING-CLASS (class NULL) name &KEY :METACLASS :DIRECT-SUPERCLASSES &ALLOW-OTHER-KEYS)
This method implements the behavior of the generic function in the case where the class argument is NIL.
29.1.3.6.4. Generic Function CLOS:FINALIZE-INHERITANCE
Syntax
(CLOS:FINALIZE-INHERITANCE class)
Arguments
Values
The value returned by this generic function is unspecified.
Purpose

This generic function is called to finalize a class metaobject. This is described in Section 29.1.3.4, “Class Finalization Protocol”

After CLOS:FINALIZE-INHERITANCE returns, the class metaobject is finalized and the result of calling CLOS:CLASS-FINALIZED-P on the class metaobject will be true.

Methods

(CLOS:FINALIZE-INHERITANCE (class STANDARD-CLASS))
(CLOS:FINALIZE-INHERITANCE (class CLOS:FUNCALLABLE-STANDARD-CLASS))
No behavior is specified for these methods beyond that which is specified for their respective generic functions.
(CLOS:FINALIZE-INHERITANCE (class CLOS:FORWARD-REFERENCED-CLASS))
This method SIGNALs an ERROR.
29.1.3.6.5. Generic Function MAKE-INSTANCE
Syntax
(MAKE-INSTANCE class &REST initargs)
Arguments
class
a class metaobject or a class name.
initargs
a list of alternating initialization argument names and values.
Values
The result is a newly allocated and initialized instance of class.
Purpose
The generic function MAKE-INSTANCE creates and returns a new instance of the given class. Its behavior and use is described in the [ANSI CL].

Methods

(MAKE-INSTANCE (class SYMBOL) &REST initargs)
This method simply invokes MAKE-INSTANCE recursively on the arguments (FIND-CLASS class) and initargs.
(MAKE-INSTANCE (class STANDARD-CLASS) &REST initargs)
(MAKE-INSTANCE (class CLOS:FUNCALLABLE-STANDARD-CLASS) &REST initargs)
These methods implement the behavior of MAKE-INSTANCE described in the [ANSI CL] section 7.1 “Object Creation and Initialization.
29.1.3.6.6. Generic Function ALLOCATE-INSTANCE
Syntax
(ALLOCATE-INSTANCE class &REST initargs)
Arguments
class
a class metaobject.
initargs
alternating initialization argument names and values.
Values
The value returned is a newly allocated instance of class
Purpose

This generic function is called to create a new, uninitialized instance of a class. The interpretation of the concept of an uninitialized instance depends on the class metaobject class.

Before allocating the new instance, CLOS:CLASS-FINALIZED-P is called to see if class has been finalized. If it has not been finalized, CLOS:FINALIZE-INHERITANCE is called before the new instance is allocated.

Methods

(ALLOCATE-INSTANCE (class STANDARD-CLASS) &REST initargs
This method allocates storage in the instance for each slot with allocation :INSTANCE. These slots are unbound. Slots with any other allocation are ignored by this method (no ERROR is SIGNALed).
(ALLOCATE-INSTANCE (class CLOS:FUNCALLABLE-STANDARD-CLASS) &REST initargs)

This method allocates storage in the instance for each slot with allocation :INSTANCE. These slots are unbound. Slots with any other allocation are ignored by this method (no ERROR is SIGNALed).

The funcallable instance function of the instance is undefined - the results are undefined if the instance is applied to arguments before CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION has been used to set the funcallable instance function.

(ALLOCATE-INSTANCE (class BUILT-IN-CLASS) &REST initargs)
This method SIGNALs an ERROR.
29.1.3.6.7. Generic Function CLOS:VALIDATE-SUPERCLASS
Syntax
(CLOS:VALIDATE-SUPERCLASS class superclass)
Arguments
Values
This generic function returns true or false.
Purpose

This generic function is called to determine whether the class superclass is suitable for use as a superclass of class.

This generic function can be be called by the implementation or user code. It is called during class metaobject initialization and reinitialization, before the direct superclasses are stored. If this generic function returns false, the initialization or reinitialization will signal an error.

Methods

(CLOS:VALIDATE-SUPERCLASS (class CLASS) (superclass CLASS))

This method returns true in three situations:

  1. If the superclass argument is the class named T,
  2. if the class of the class argument is the same as the class of the superclass argument, or
  3. if the class of one of the arguments is STANDARD-CLASS and the class of the other is CLOS:FUNCALLABLE-STANDARD-CLASS.

In all other cases, this method returns false.

This method can be overridden.

Implementation dependent: only in CLISP

This method also returns true in a fourth situation:

  1. If the class of the class argument is a subclass of the class of the superclass argument.

Remarks. Defining a method on CLOS:VALIDATE-SUPERCLASS requires detailed knowledge of of the internal protocol followed by each of the two class metaobject classes. A method on CLOS:VALIDATE-SUPERCLASS which returns true for two different class metaobject classes declares that they are compatible.

29.1.3.6.8. Generic Function CLOS:COMPUTE-DIRECT-SLOT-DEFINITION-INITARGS

Implementation dependent: only in CLISP

Syntax
(CLOS:COMPUTE-DIRECT-SLOT-DEFINITION-INITARGS class &REST slot-spec)
Arguments
Values
The value returned by this generic function is a list of initialization arguments for a direct slot definition metaobject.
Purpose

This generic function determines the initialization arguments for the direct slot definition for a slot in a class. It is called during initialization of a class. The resulting initialization arguments are passed to CLOS:DIRECT-SLOT-DEFINITION-CLASS and then to MAKE-INSTANCE.

This generic function uses the supplied canonicalized slot specification. The value of :NAME in the returned initargs is the same as the value of :NAME in the supplied slot-spec argument.

Methods

(CLOS:COMPUTE-DIRECT-SLOT-DEFINITION-INITARGS (class STANDARD-CLASS) &REST slot-spec)
(CLOS:COMPUTE-DIRECT-SLOT-DEFINITION-INITARGS (class CLOS:FUNCALLABLE-STANDARD-CLASS) &REST slot-spec)

This method returns slot-spec unmodified.

This method can be overridden.

29.1.3.6.9. Generic Function CLOS:DIRECT-SLOT-DEFINITION-CLASS
Syntax
(CLOS:DIRECT-SLOT-DEFINITION-CLASS class &REST initargs)
Arguments
class
a class metaobject.
initargs
a set of initialization arguments and values.
Values
The value returned is a subclass of the class CLOS:DIRECT-SLOT-DEFINITION.
Purpose

When a class is initialized, each of the canonicalized slot specifications must be converted to a direct slot definition metaobject. This generic function is called to determine the class of that direct slot definition metaobject.

The initargs argument is simply the canonicalized slot specification for the slot.

Methods

(CLOS:DIRECT-SLOT-DEFINITION-CLASS (class STANDARD-CLASS) &REST initargs)
(CLOS:DIRECT-SLOT-DEFINITION-CLASS (class CLOS:FUNCALLABLE-STANDARD-CLASS) &REST initargs)

These methods return the class CLOS:STANDARD-DIRECT-SLOT-DEFINITION.

These methods can be overridden.

29.1.3.6.10. Generic Function CLOS:COMPUTE-CLASS-PRECEDENCE-LIST
Syntax
(CLOS:COMPUTE-CLASS-PRECEDENCE-LIST class)
Arguments
Values
The value returned by this generic function is a list of class metaobjects.
Purpose

This generic-function is called to determine the class precedence list of a class.

The result is a list which contains each of class and its superclasses once and only once. The first element of the list is class and the last element is the class named T.

All methods on this generic function must compute the class precedence list as a function of the ordered direct superclasses of the superclasses of class. The results are undefined if the rules used to compute the class precedence list depend on any other factors.

When a class is finalized, CLOS:FINALIZE-INHERITANCE calls this generic function and associates the returned value with the class metaobject. The value can then be accessed by calling CLOS:CLASS-PRECEDENCE-LIST.

The list returned by this function will not be mutated by the implementation. The results are undefined if a portable program mutates the list returned by this function.

Methods

(CLOS:COMPUTE-CLASS-PRECEDENCE-LIST (class CLASS))

This method computes the class precedence list according to the rules described in the [ANSI CL] section 4.3.5 “Determining the Class Precedence List.

This method SIGNALs an ERROR if class or any of its superclasses is a forward referenced class.

This method can be overridden.

29.1.3.6.11. Generic Function CLOS:COMPUTE-SLOTS
Syntax
(CLOS:COMPUTE-SLOTS class)
Arguments
Values
The value returned is a set of effective slot definition metaobjects.
Purpose

This generic function computes a set of effective slot definition metaobjects for the class class. The result is a list of effective slot definition metaobjects: one for each slot that will be accessible in instances of class.

This generic function proceeds in 3 steps:

The first step collects the full set of direct slot definitions from the superclasses of class.

The direct slot definitions are then collected into individual lists, one list for each slot name associated with any of the direct slot definitions. The slot names are compared with EQL. Each such list is then sorted into class precedence list order. Direct slot definitions coming from classes earlier in the class precedence list of class appear before those coming from classes later in the class precedence list. For each slot name, the generic function CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION is called to compute an effective slot definition. The result of CLOS:COMPUTE-SLOTS is a list of these effective slot definitions, in unspecified order.

In the final step, the location for each effective slot definition is set. This is done by specified around-methods; portable methods cannot take over this behavior. For more information on the slot definition locations, see Section 29.1.10.1, “Instance Structure Protocol”.

The list returned by this function will not be mutated by the implementation. The results are undefined if a portable program mutates the list returned by this function.

Methods

(CLOS:COMPUTE-SLOTS (class STANDARD-CLASS))
(CLOS:COMPUTE-SLOTS (class CLOS:FUNCALLABLE-STANDARD-CLASS)}

These methods implement the specified behavior of the generic function.

These methods can be overridden.

(CLOS:COMPUTE-SLOTS :AROUND (class STANDARD-CLASS))
(CLOS:COMPUTE-SLOTS :AROUND (class CLOS:FUNCALLABLE-STANDARD-CLASS))
These methods implement the specified behavior of computing and storing slot locations. These methods cannot be overridden.
29.1.3.6.12. Generic Function CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION
Syntax
(CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION class name direct-slot-definitions)
Arguments
class
a class metaobject.
name
a slot name.
direct-slot-definitions
an ordered list of direct slot definition metaobjects. The most specific direct slot definition metaobject appears first in the list.
Values
The value returned by this generic function is an effective slot definition metaobject.
Purpose

This generic function determines the effective slot definition for a slot in a class. It is called by CLOS:COMPUTE-SLOTS once for each slot accessible in instances of class.

This generic function uses the supplied list of direct slot definition metaobjects to compute the inheritance of slot properties for a single slot. The returned effective slot definition represents the result of computing the inheritance. The name of the new effective slot definition is the same as the name of the direct slot definitions supplied.

The class of the effective slot definition metaobject is determined by calling CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS. The effective slot definition is then created by calling MAKE-INSTANCE. The initialization arguments passed in this call to MAKE-INSTANCE are used to initialize the new effective slot definition metaobject. See Section 29.1.4, “Slot Definitions” for details.

Methods

(CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION (class STANDARD-CLASS) name direct-slot-definitions)
(CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION (class CLOS:FUNCALLABLE-STANDARD-CLASS) name direct-slot-definitions)

This method implements the inheritance and defaulting of slot options following the rules described in the [ANSI CL] section 7.5.3 “Inheritance of Slots and Options.

This method can be extended, but the value returned by the extending method must be the value returned by this method.

Implementation dependent: only in CLISP

The initialization arguments that are passed to CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS and MAKE-INSTANCE are computed through a call to CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS. It is the CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS method that implements the inheritance rules.

Implementation dependent: only in CLISP

Syntax
(CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS class direct-slot-definitions)
Arguments
class
a class metaobject.
direct-slot-definitions
an ordered list of direct slot definition metaobjects. The most specific direct slot definition metaobject appears first in the list.
Values
The value returned by this generic function is a list of initialization arguments for an effective slot definition metaobject.
Purpose

This generic function determines the initialization arguments for the effective slot definition for a slot in a class. It is called by CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION. The resulting initialization arguments are passed to CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS and then to MAKE-INSTANCE.

This generic function uses the supplied list of direct slot definition metaobjects to compute the inheritance of slot properties for a single slot. The returned effective slot definition initargs represent the result of computing the inheritance. The value of :NAME in the returned initargs is the same as the name of the direct slot definitions supplied.

Methods

(CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS (class STANDARD-CLASS) direct-slot-definitions)
(CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS (class CLOS:FUNCALLABLE-STANDARD-CLASS) direct-slot-definitions)

This method implements the inheritance and defaulting of slot options following the rules described in the [ANSI CL] section 7.5.3 “Inheritance of Slots and Options.

This method can be extended.

29.1.3.6.14. Generic Function CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS
Syntax
(CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS class &REST initargs)
Arguments
class
a class metaobject.
initargs
set of initialization arguments and values.
Values
The value returned is a subclass of the class CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS.
Purpose
This generic function is called by CLOS:COMPUTE-EFFECTIVE-SLOT-DEFINITION to determine the class of the resulting effective slot definition metaobject. The initargs argument is the set of initialization arguments and values that will be passed to MAKE-INSTANCE when the effective slot definition metaobject is created.

Methods

(CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS (class STANDARD-CLASS) &REST initargs)
(CLOS:EFFECTIVE-SLOT-DEFINITION-CLASS (class CLOS:FUNCALLABLE-STANDARD-CLASS) &REST initargs)

These methods return the class CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION.

These methods can be overridden.

29.1.3.6.15. Generic Function CLOS:COMPUTE-DEFAULT-INITARGS
Syntax
(CLOS:COMPUTE-DEFAULT-INITARGS class)
Arguments
Values
The value returned by this generic function is a list of canonicalized default initialization arguments.
Purpose

This generic-function is called to determine the default initialization arguments for a class.

The result is a list of canonicalized default initialization arguments, with no duplication among initialization argument names.

All methods on this generic function must compute the default initialization arguments as a function of only:

  1. the class precedence list of class, and
  2. the direct default initialization arguments of each class in that list.

The results are undefined if the rules used to compute the default initialization arguments depend on any other factors.

When a class is finalized, CLOS:FINALIZE-INHERITANCE calls this generic function and associates the returned value with the class metaobject. The value can then be accessed by calling CLOS:CLASS-DEFAULT-INITARGS.

The list returned by this function will not be mutated by the implementation. The results are undefined if a portable program mutates the list returned by this function.

Methods

(CLOS:COMPUTE-DEFAULT-INITARGS (class STANDARD-CLASS))
(CLOS:COMPUTE-DEFAULT-INITARGS (class CLOS:FUNCALLABLE-STANDARD-CLASS))

These methods compute the default initialization arguments according to the rules described in the [ANSI CL] section 7.1.3 “Defaulting of Initialization Arguments.

These methods signal an error if class or any of its superclasses is a forward referenced class.

These methods can be overridden.

29.1.3.7. Updating Dependencies

29.1.3.7.1. Generic Function CLOS:ADD-DIRECT-SUBCLASS
Syntax
(CLOS:ADD-DIRECT-SUBCLASS superclass subclass)
Arguments
superclass
a class metaobject.
subclass
a class metaobject.
Values
The value returned by this generic function is unspecified.
Purpose

This generic function is called to maintain a set of backpointers from a class to its direct subclasses. This generic function adds subclass to the set of direct subclasses of superclass.

When a class is initialized, this generic function is called once for each direct superclass of the class.

When a class is reinitialized, this generic function is called once for each added direct superclass of the class. The generic function CLOS:REMOVE-DIRECT-SUBCLASS is called once for each deleted direct superclass of the class.

Methods

(CLOS:ADD-DIRECT-SUBCLASS (superclass CLASS) (subclass CLASS))

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:

29.1.3.7.2. Generic Function CLOS:REMOVE-DIRECT-SUBCLASS
Syntax
(CLOS:REMOVE-DIRECT-SUBCLASS superclass subclass)
Arguments
superclass
a class metaobject.
subclass
a class metaobject.
Values
The value returned by this generic function is unspecified.
Purpose

This generic function is called to maintain a set of backpointers from a class to its direct subclasses. It removes subclass from the set of direct subclasses of superclass. No ERROR is SIGNALed if subclass is not in this set.

Whenever a class is reinitialized, this generic function is called once with each deleted direct superclass of the class.

Methods

(CLOS:REMOVE-DIRECT-SUBCLASS (superclass CLASS) (subclass CLASS))

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:

29.1.4. Slot Definitions

29.1.4.1. Inheritance Structure of slot definition metaobject Classes

Figure 29.3. Inheritance structure of slot definition metaobject classes

Inheritance structure of slot definition metaobject classes

29.1.4.2. Introspection: Readers for slot definition metaobjects

The reader generic functions which simply return information associated with slot definition metaobjects are presented together here in the format described in Section 29.1.3.3, “Introspection: Readers for class metaobjects”.

Each of the reader generic functions for slot definition metaobjects has the same syntax, accepting one required argument called slot, which must be a slot definition metaobject; otherwise, an ERROR is SIGNALed. An ERROR is also SIGNALed if the slot definition metaobject has not been initialized.

These generic functions can be called by the user or the implementation.

For any of these generic functions which returns a list, such lists will not be mutated by the implementation. The results are undefined if a portable program allows such a list to be mutated.

29.1.4.2.1. Generic Functions
29.1.4.2.1.1. Generic Function CLOS:SLOT-DEFINITION-NAME

Returns the name of slot. This value is a symbol that can be used as a variable name. This is the value of the :NAME initialization argument that was associated with the slot definition metaobject during initialization.

Implementation dependent: only in CLISP

The slot name does not need to be usable as a variable name. Slot names like NIL or T are perfectly valid.

Returns the allocation of slot. This is a symbol. This is the defaulted value of the :ALLOCATION initialization argument that was associated with the slot definition metaobject during initialization.

29.1.4.2.1.3. Generic Function CLOS:SLOT-DEFINITION-INITFORM

Returns the initialization form of slot. This can be any form. This is the defaulted value of the :INITFORM initialization argument that was associated with the slot definition metaobject during initialization. When slot has no initialization form, the value returned is unspecified (however, CLOS:SLOT-DEFINITION-INITFUNCTION is guaranteed to return NIL).

Returns the initialization function of slot. This value is either a function of no arguments, or NIL, indicating that the slot has no initialization function. This is the defaulted value of the :INITFUNCTION initialization argument that was associated with the slot definition metaobject during initialization.

29.1.4.2.1.5. Generic Function CLOS:SLOT-DEFINITION-TYPE

Returns the type of slot. This is a type specifier name. This is the defaulted value of the :TYPE initialization argument that was associated with the slot definition metaobject during initialization.

29.1.4.2.1.6. Generic Function CLOS:SLOT-DEFINITION-INITARGS

Returns the set of initialization argument keywords for slot. This is the defaulted value of the :INITARGS initialization argument that was associated with the slot definition metaobject during initialization.

29.1.4.2.2. Methods

The specified methods for the slot definition metaobject readers

(CLOS:SLOT-DEFINITION-NAME (slot-definition CLOS:STANDARD-SLOT-DEFINITION))
(CLOS:SLOT-DEFINITION-ALLOCATION (slot-definition CLOS:STANDARD-SLOT-DEFINITION))
(CLOS:SLOT-DEFINITION-INITFORM (slot-definition CLOS:STANDARD-SLOT-DEFINITION))
(CLOS:SLOT-DEFINITION-INITFUNCTION (slot-definition CLOS:STANDARD-SLOT-DEFINITION))
(CLOS:SLOT-DEFINITION-TYPE (slot-definition CLOS:STANDARD-SLOT-DEFINITION))
(CLOS:SLOT-DEFINITION-INITARGS (slot-definition CLOS:STANDARD-SLOT-DEFINITION))
No behavior is specified for these methods beyond that which is specified for their respective generic functions.
29.1.4.2.3. Readers for direct slot definition metaobjects

The following additional reader generic functions are defined for direct slot definition metaobjects.

29.1.4.2.3.1. Generic Function CLOS:SLOT-DEFINITION-READERS
(CLOS:SLOT-DEFINITION-READERS direct-slot-definition)

Returns a (possibly empty) set of readers of the direct-slot-definition. This value is a list of function names. This is the defaulted value of the :READERS initialization argument that was associated with the direct slot definition metaobject during initialization.

29.1.4.2.3.2. Generic Function CLOS:SLOT-DEFINITION-WRITERS
(CLOS:SLOT-DEFINITION-WRITERS direct-slot-definition)

Returns a (possibly empty) set of writers of the direct-slot-definition. This value is a list of function names. This is the defaulted value of the :WRITERS initialization argument that was associated with the direct slot definition metaobject during initialization.

(CLOS:SLOT-DEFINITION-READERS (direct-slot-definition CLOS:STANDARD-DIRECT-SLOT-DEFINITION))
(CLOS:SLOT-DEFINITION-WRITERS (direct-slot-definition CLOS:STANDARD-DIRECT-SLOT-DEFINITION))
No behavior is specified for these methods beyond that which is specified for their respective generic functions.

29.1.4.2.4. Readers for effective slot definition metaobjects

The following reader generic function is defined for effective slot definition metaobjects.

29.1.4.2.4.1. Generic Function CLOS:SLOT-DEFINITION-LOCATION
(CLOS:SLOT-DEFINITION-LOCATION effective-slot-definition)

Returns the location of effective-slot-definition. The meaning and interpretation of this value is described in Section 29.1.10.1, “Instance Structure Protocol”.

(CLOS:SLOT-DEFINITION-LOCATION (effective-slot-definition CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))
This method returns the value stored by CLOS:COMPUTE-SLOTS :AROUND (STANDARD-CLASS) and CLOS:COMPUTE-SLOTS :AROUND (CLOS:FUNCALLABLE-STANDARD-CLASS).

29.1.4.3. Initialization of slot definition metaobjects

A slot definition metaobject can be created by calling MAKE-INSTANCE. The initialization arguments establish the definition of the slot definition. A slot definition metaobject cannot be redefined; calling REINITIALIZE-INSTANCE SIGNALs an ERROR.

Initialization of a slot definition metaobject must be done by calling MAKE-INSTANCE and allowing it to call INITIALIZE-INSTANCE. Portable programs must not...

Since metaobject classes may not be redefined, no behavior is specified for the result of calls to UPDATE-INSTANCE-FOR-REDEFINED-CLASS on slot definition metaobjects. Since the class of a slot definition metaobject cannot be changed, no behavior is specified for the result of calls to UPDATE-INSTANCE-FOR-DIFFERENT-CLASS on slot definition metaobjects.

During initialization, each initialization argument is checked for errors and then associated with the slot definition metaobject. The value can then be accessed by calling the appropriate accessor as shown in Table 29.3, “Initialization arguments and accessors for slot definition metaobjects”.

This section begins with a description of the error checking and processing of each initialization argument. This is followed by a table showing the generic functions that can be used to access the stored initialization arguments.

In these descriptions, the phrase “this argument defaults to value” means that when that initialization argument is not supplied, initialization is performed as if value had been supplied. For some initialization arguments this could be done by the use of default initialization arguments, but whether it is done this way is not specified. Implementations are free to define default initialization arguments for specified slot definition metaobject classes. Portable programs are free to define default initialization arguments for portable subclasses of the class CLOS:SLOT-DEFINITION.

  • The :NAME argument is a slot name. An ERROR is SIGNALed if this argument is not a symbol which can be used as a variable name. An ERROR is SIGNALed if this argument is not supplied.

    Implementation dependent: only in CLISP

    The :NAME argument does not need to be usable as a variable name. Slot names like NIL or T are perfectly valid.

  • The :INITFORM argument is a form. The :INITFORM argument defaults to NIL. An ERROR is SIGNALed if the :INITFORM argument is supplied, but the :INITFUNCTION argument is not supplied.
  • The :INITFUNCTION argument is a function of zero arguments which, when called, evaluates the :INITFORM in the appropriate lexical environment. The :INITFUNCTION argument defaults to false. An ERROR is SIGNALed if the :INITFUNCTION argument is supplied, but the :INITFORM argument is not supplied.
  • The :TYPE argument is a type specifier name. An ERROR is SIGNALed otherwise. The :TYPE argument defaults to the symbol T.
  • The :ALLOCATION argument is a SYMBOL. An ERROR is SIGNALed otherwise. The :ALLOCATION argument defaults to the symbol :INSTANCE.
  • The :INITARGS argument is a LIST of SYMBOLs. An ERROR is SIGNALed if this argument is not a proper list, or if any element of this list is not a SYMBOL. The :INITARGS argument defaults to the empty list.
  • The :READERS and :WRITERS arguments are LISTs of function names. An ERROR is SIGNALed if they are not proper lists, or if any element is not a valid function name. They default to the empty list. An ERROR is SIGNALed if either of these arguments is supplied and the metaobject is not a CLOS:DIRECT-SLOT-DEFINITION.
  • The :DOCUMENTATION argument is a STRING or NIL. An ERROR is SIGNALed if it is not. This argument default to NIL during initialization.

After the processing and defaulting of initialization arguments described above, the value of each initialization argument is associated with the slot definition metaobject. These values can then be accessed by calling the corresponding generic function. The correspondences are as follows:

Table 29.3. Initialization arguments and accessors for slot definition metaobjects


29.1.4.3.1. Methods

It is not specified which methods provide the initialization and reinitialization behavior described above. Instead, the information needed to allow portable programs to specialize this behavior is presented as a set of restrictions on the methods a portable program can define. The model is that portable initialization methods have access to the slot definition metaobject when either all or none of the specified initialization has taken effect.

These restrictions govern the methods that a portable program can define on the generic functions INITIALIZE-INSTANCE, REINITIALIZE-INSTANCE, and SHARED-INITIALIZE. These restrictions apply only to methods on these generic functions for which the first specializer is a subclass of the class CLOS:SLOT-DEFINITION. Other portable methods on these generic functions are not affected by these restrictions.

  • Portable programs must not define methods on SHARED-INITIALIZE or REINITIALIZE-INSTANCE.
  • For INITIALIZE-INSTANCE:

    • Portable programs must not define primary methods.
    • Portable programs may define around-methods, but these must be extending, not overriding methods.
    • Portable before-methods must assume that when they are run, none of the initialization behavior described above has been completed.
    • Portable after-methods must assume that when they are run, all of the initialization behavior described above has been completed.

The results are undefined if any of these restrictions are violated.

29.1.5. Generic Functions

29.1.5.1. Inheritance Structure of generic function metaobject Classes

Figure 29.4. Inheritance structure of generic function metaobject classes

Inheritance structure of generic function metaobject classes

29.1.5.2. Introspection: Readers for generic function metaobjects

The reader generic functions which simply return information associated with generic function metaobjects are presented together here in the format described in Section 29.1.3.3, “Introspection: Readers for class metaobjects”.

Each of the reader generic functions for generic function metaobjects has the same syntax, accepting one required argument called generic-function, which must be a generic function metaobject; otherwise, an ERROR is SIGNALed. An ERROR is also SIGNALed if the generic function metaobject has not been initialized.

These generic functions can be called by the user or the implementation.

For any of these generic functions which returns a list, such lists will not be mutated by the implementation. The results are undefined if a portable program allows such a list to be mutated.

29.1.5.2.1. Generic Function CLOS:GENERIC-FUNCTION-NAME
(CLOS:GENERIC-FUNCTION-NAME generic-function)

Returns the name of the generic function, or NIL if the generic function has no name. This is the defaulted value of the :NAME initialization argument that was associated with the generic function metaobject during initialization or reinitialization. (See also (SETF CLOS:GENERIC-FUNCTION-NAME).)

29.1.5.2.2. Generic Function CLOS:GENERIC-FUNCTION-METHODS

Returns the set of methods currently connected to the generic function. This is a set of method metaobjects. This value is maintained by the generic functions ADD-METHOD and REMOVE-METHOD.

29.1.5.2.3. Generic Function CLOS:GENERIC-FUNCTION-LAMBDA-LIST

Returns the lambda list of the generic function. This is the defaulted value of the :LAMBDA-LIST initialization argument that was associated with the generic function metaobject during initialization or reinitialization. An ERROR is SIGNALed if the lambda list has yet to be supplied.

Returns the argument precedence order of the generic function. This value is a list of symbols, a permutation of the required parameters in the lambda list of the generic function. This is the defaulted value of the :ARGUMENT-PRECEDENCE-ORDER initialization argument that was associated with the generic function metaobject during initialization or reinitialization.

Implementation dependent: only in CLISP

An ERROR is SIGNALed if the lambda list has not yet been supplied.

29.1.5.2.5. Generic Function CLOS:GENERIC-FUNCTION-DECLARATIONS

Returns a possibly empty list of the “declarations” of the generic function. The elements of this list are declaration specifiers. This list is the defaulted value of the :DECLARATIONS initialization argument that was associated with the generic function metaobject during initialization or reinitialization.

29.1.5.2.6. Generic Function CLOS:GENERIC-FUNCTION-METHOD-CLASS

Returns the default method class of the generic function. This class must be a subclass of the class METHOD. This is the defaulted value of the :METHOD-CLASS initialization argument that was associated with the generic function metaobject during initialization or reinitialization.

Returns the method combination of the generic function. This is a method combination metaobject. This is the defaulted value of the :METHOD-COMBINATION initialization argument that was associated with the generic function metaobject during initialization or reinitialization.

29.1.5.2.8. Methods

The specified methods for the generic function metaobject reader generic functions

(CLOS:GENERIC-FUNCTION-NAME (generic-function STANDARD-GENERIC-FUNCTION))
(CLOS:GENERIC-FUNCTION-LAMBDA-LIST (generic-function STANDARD-GENERIC-FUNCTION))
(CLOS:GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER (generic-function STANDARD-GENERIC-FUNCTION))
(CLOS:GENERIC-FUNCTION-DECLARATIONS (generic-function STANDARD-GENERIC-FUNCTION))
(CLOS:GENERIC-FUNCTION-METHOD-CLASS (generic-function STANDARD-GENERIC-FUNCTION))
(CLOS:GENERIC-FUNCTION-METHOD-COMBINATION (generic-function STANDARD-GENERIC-FUNCTION))
No behavior is specified for these methods beyond that which is specified for their respective generic functions.
(CLOS:GENERIC-FUNCTION-METHODS (generic-function STANDARD-GENERIC-FUNCTION))

No behavior is specified for this method beyond that which is specified for the generic function.

The value returned by this method is maintained by ADD-METHOD(STANDARD-GENERIC-FUNCTION STANDARD-METHOD) and REMOVE-METHOD(STANDARD-GENERIC-FUNCTION STANDARD-METHOD).

29.1.5.3. Initialization of Generic Functions

29.1.5.3.1. Macro DEFGENERIC

The evaluation or execution of a DEFGENERIC form results in a call to the ENSURE-GENERIC-FUNCTION function. The arguments received by ENSURE-GENERIC-FUNCTION are derived from the DEFGENERIC form in a defined way. As with DEFCLASS and DEFMETHOD, the exact macro-expansion of the DEFGENERIC form is not defined, only the relationship between the arguments to the macro and the arguments received by ENSURE-GENERIC-FUNCTION.

  • The function-name argument to DEFGENERIC becomes the first argument to ENSURE-GENERIC-FUNCTION. This is the only positional argument accepted by ENSURE-GENERIC-FUNCTION; all other arguments are keyword arguments.
  • The lambda-list argument to DEFGENERIC becomes the value of the :LAMBDA-LIST keyword argument to ENSURE-GENERIC-FUNCTION.
  • For each of the options :ARGUMENT-PRECEDENCE-ORDER, :DOCUMENTATION, :GENERIC-FUNCTION-CLASS and :METHOD-CLASS, the value of the option becomes the value of the keyword argument with the same name. If the option does not appear in the macro form, the keyword argument does not appear in the resulting call to ENSURE-GENERIC-FUNCTION.

    Implementation dependent: only in CLISP

    If the option does not appear in the macro form, the keyword argument appears in the resulting call to ENSURE-GENERIC-FUNCTION, with a default value: the lambda list for :ARGUMENT-PRECEDENCE-ORDER, NIL for :DOCUMENTATION, the class STANDARD-GENERIC-FUNCTION for :GENERIC-FUNCTION-CLASS, the class STANDARD-METHOD for :METHOD-CLASS. This is needed to make the generic function reflect the DEFGENERIC form.

  • For the option :DECLARE, the list of “declarations” becomes the value of the :DECLARATIONS keyword argument. If the :DECLARE option does not appear in the macro form, the :DECLARATIONS keyword argument does not appear in the call to ENSURE-GENERIC-FUNCTION.

    Implementation dependent: only in CLISP

    If the :DECLARE option does not appear in the macro form, the :DECLARATIONS keyword argument appears in the resulting call to ENSURE-GENERIC-FUNCTION, with a default value of NIL. This is needed to make the generic function reflect the DEFGENERIC form.

  • The handling of the :METHOD-COMBINATION option is not specified.

    Implementation dependent: only in CLISP

    If the :METHOD-COMBINATION option does not appear in the macro form, the :METHOD-COMBINATION keyword argument still appears in the resulting call to ENSURE-GENERIC-FUNCTION, but in a position where it can be overridden by user-defined initargs and default initargs.

  • Implementation dependent: only in CLISP

    The :DECLARE keyword is recognized as equivalent to the :DECLARATIONS keyword, for compatibility with ENSURE-GENERIC-FUNCTION in [ANSI CL]. If both :DECLARE and :DECLARATIONS keyword arguments are specified, an ERROR is SIGNALed.

    Any other generic function options become the value of keyword arguments with the same name. The value of the keyword argument is the tail of the generic function option. An ERROR is SIGNALed if any generic function option appears more than once in the DEFGENERIC form.

    The default initargs of the generic-function-class are added at the end of the list of arguments to pass to ENSURE-GENERIC-FUNCTION. This is needed to make the generic function reflect the DEFGENERIC form.

  • Implementation dependent: only in CLISP

    User-defined options. Any other options become the value of keyword arguments with the same name. The value of the keyword argument is the tail of the option. An ERROR is SIGNALed if any option appears more than once in the DEFGENERIC form.

The result of the call to ENSURE-GENERIC-FUNCTION is returned as the result of evaluating or executing the DEFGENERIC form.

29.1.5.3.2. Generic Function Invocation Protocol

Associated with each generic function is its discriminating function. Each time the generic function is called, the discriminating function is called to provide the behavior of the generic function. The discriminating function receives the full set of arguments received by the generic function. It must lookup and execute the appropriate methods, and return the appropriate values.

The discriminating function is computed by the highest layer of the generic function invocation protocol, CLOS:COMPUTE-DISCRIMINATING-FUNCTION. Whenever a generic function metaobject is initialized, reinitialized, or a method is added or removed, the discriminating function is recomputed. The new discriminating function is then stored with CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION.

Discriminating functions call CLOS:COMPUTE-APPLICABLE-METHODS and CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES to compute the methods applicable to the generic functions arguments. Applicable methods are combined by CLOS:COMPUTE-EFFECTIVE-METHOD to produce an effective method. Provisions are made to allow memoization of the method applicability and effective methods computations. (See the description of CLOS:COMPUTE-DISCRIMINATING-FUNCTION for details.)

The body of method definitions are processed by CLOS:MAKE-METHOD-LAMBDA. The result of this generic function is a lambda expression which is processed by either COMPILE or COMPILE-FILE to produce a method function. The arguments received by the method function are controlled by the CALL-METHOD forms appearing in the effective methods. By default, method functions accept two arguments: a list of arguments to the generic function, and a list of next methods. The list of next methods corresponds to the next methods argument to CALL-METHOD. If CALL-METHOD appears with additional arguments, these will be passed to the method functions as well; in these cases, CLOS:MAKE-METHOD-LAMBDA must have created the method lambdas to expect additional arguments.

29.1.5.3.3. Initialization of generic function metaobjects

A generic function metaobject can be created by calling MAKE-INSTANCE. The initialization arguments establish the definition of the generic function. A generic function metaobject can be redefined by calling REINITIALIZE-INSTANCE. Some classes of generic function metaobject do not support redefinition; in these cases, REINITIALIZE-INSTANCE SIGNALs an ERROR.

Initialization of a generic function metaobject must be done by calling MAKE-INSTANCE and allowing it to call INITIALIZE-INSTANCE. Reinitialization of a generic-function metaobject must be done by calling REINITIALIZE-INSTANCE. Portable programs must not

Since metaobject classes may not be redefined, no behavior is specified for the result of calls to UPDATE-INSTANCE-FOR-REDEFINED-CLASS on generic function metaobjects. Since the class of a generic function metaobject may not be changed, no behavior is specified for the results of calls to UPDATE-INSTANCE-FOR-DIFFERENT-CLASS on generic function metaobjects.

During initialization or reinitialization, each initialization argument is checked for errors and then associated with the generic function metaobject. The value can then be accessed by calling the appropriate accessor as shown in Table 29.4, “Initialization arguments and accessors for generic function metaobjects”.

This section begins with a description of the error checking and processing of each initialization argument. This is followed by a table showing the generic functions that can be used to access the stored initialization arguments. The section ends with a set of restrictions on portable methods affecting generic function metaobject initialization and reinitialization.

In these descriptions, the phrase “this argument defaults to value” means that when that initialization argument is not supplied, initialization or reinitialization is performed as if value had been supplied. For some initialization arguments this could be done by the use of default initialization arguments, but whether it is done this way is not specified. Implementations are free to define default initialization arguments for specified generic function metaobject classes. Portable programs are free to define default initialization arguments for portable subclasses of the class GENERIC-FUNCTION.

Unless there is a specific note to the contrary, then during reinitialization, if an initialization argument is not supplied, the previously stored value is left unchanged.

  • The :ARGUMENT-PRECEDENCE-ORDER argument is a list of symbols.

    An ERROR is SIGNALed if this argument appears but the :LAMBDA-LIST argument does not appear. An ERROR is SIGNALed if this value is not a proper list or if this value is not a permutation of the symbols from the required arguments part of the :LAMBDA-LIST initialization argument.

    When the generic function is being initialized or reinitialized, and this argument is not supplied, but the :LAMBDA-LIST argument is supplied, this value defaults to the symbols from the required arguments part of the :LAMBDA-LIST argument, in the order they appear in that argument. If neither argument is supplied, neither are initialized (see the description of :LAMBDA-LIST.)

  • The :DECLARATIONS argument is a list of declaration specifiers.

    An ERROR is SIGNALed if this value is not a proper list or if each of its elements is not a legal declaration specifier.

    When the generic function is being initialized, and this argument is not supplied, it defaults to the empty list.

  • The :DOCUMENTATION argument is a STRING or NIL. An ERROR is SIGNALed if it is not. This argument default to NIL during initialization.
  • The :LAMBDA-LIST argument is a lambda list.

    An ERROR is SIGNALed if this value is not a proper generic function lambda list.

    When the generic function is being initialized, and this argument is not supplied, the generic function's lambda list is not initialized. The lambda list will be initialized later, either when the first method is added to the generic function, or a later reinitialization of the generic function.

  • The :METHOD-COMBINATION argument is a method combination metaobject.
  • The :METHOD-CLASS argument is a class metaobject.

    An ERROR is SIGNALed if this value is not a subclass of the class METHOD.

    When the generic function is being initialized, and this argument is not supplied, it defaults to the class STANDARD-METHOD.

  • The :NAME argument is an object.

    If the generic function is being initialized, this argument defaults to NIL.

After the processing and defaulting of initialization arguments described above, the value of each initialization argument is associated with the generic function metaobject. These values can then be accessed by calling the corresponding generic function. The correspondences are as follows:

Table 29.4. Initialization arguments and accessors for generic function metaobjects


29.1.5.3.3.1. Methods

It is not specified which methods provide the initialization and reinitialization behavior described above. Instead, the information needed to allow portable programs to specialize this behavior is presented as a set of restrictions on the methods a portable program can define. The model is that portable initialization methods have access to the generic function metaobject when either all or none of the specified initialization has taken effect.

These restrictions govern the methods that a portable program can define on the generic functions INITIALIZE-INSTANCE, REINITIALIZE-INSTANCE, and SHARED-INITIALIZE. These restrictions apply only to methods on these generic functions for which the first specializer is a subclass of the class GENERIC-FUNCTION. Other portable methods on these generic functions are not affected by these restrictions.

  • Portable programs must not define methods on SHARED-INITIALIZE.
  • For INITIALIZE-INSTANCE and REINITIALIZE-INSTANCE:

    • Portable programs must not define primary methods.
    • Portable programs may define around-methods, but these must be extending, not overriding methods.
    • Portable before-methods must assume that when they are run, none of the initialization behavior described above has been completed.
    • Portable after-methods must assume that when they are run, all of the initialization behavior described above has been completed.

The results are undefined if any of these restrictions are violated.

29.1.5.4. Customization

29.1.5.4.1. Generic Function (SETF CLOS:GENERIC-FUNCTION-NAME)
Syntax
((SETF CLOS:GENERIC-FUNCTION-NAME) new-name generic-function)
Arguments
generic-function
a generic function metaobject.
new-name
a function name or NIL.
Values
This function returns its new-name argument.
Purpose

This function changes the name of generic-function to new-name. This value is usually a function name or NIL, if the generic function is to have no name.

This function works by calling REINITIALIZE-INSTANCE with generic-function as its first argument, the symbol :NAME as its second argument and new-name as its third argument.

29.1.5.4.2. Generic Function ENSURE-GENERIC-FUNCTION
Syntax
(ENSURE-GENERIC-FUNCTION function-name &KEY &ALLOW-OTHER-KEYS)
Arguments
function-name
a function name
keyword arguments
Some of the keyword arguments accepted by this function are actually processed by CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS, others are processed during initialization of the generic function metaobject (as described in Section 29.1.5.3.3, “Initialization of generic function metaobjects”).
Values
The result is a generic function metaobject.
Purpose

This function is called to define a globally named generic function or to specify or modify options and declarations that pertain to a globally named generic function as a whole. It can be called by the user or the implementation.

It is the functional equivalent of DEFGENERIC, and is called by the expansion of the DEFGENERIC and DEFMETHOD macros.

The behavior of this function is actually implemented by the generic function CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS. When ENSURE-GENERIC-FUNCTION is called, it immediately calls CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS and returns that result as its own.

The first argument to CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS is computed as follows:

  • If function-name names a non-generic function, a macro, or a special form, an ERROR is SIGNALed.
  • If function-name names a generic function, that generic function metaobject is used.
  • Otherwise, NIL is used.

The second argument is function-name. The remaining arguments are the complete set of keyword arguments received by ENSURE-GENERIC-FUNCTION.

29.1.5.4.3. Generic Function CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS
Syntax
(CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS generic-function function-name &KEY :ARGUMENT-PRECEDENCE-ORDER :DECLARATIONS :DOCUMENTATION :GENERIC-FUNCTION-CLASS :LAMBDA-LIST :METHOD-CLASS :METHOD-COMBINATION :NAME &ALLOW-OTHER-KEYS)
Arguments
generic-function
a generic function metaobject or NIL.
function-name
a function name
:GENERIC-FUNCTION-CLASS
a class metaobject or a class name. If it is not supplied, it defaults to the class named STANDARD-GENERIC-FUNCTION. If a class name is supplied, it is interpreted as the class with that name. If a class name is supplied, but there is no such class, an ERROR is SIGNALed.
additional keyword arguments

see Section 29.1.5.3.3, “Initialization of generic function metaobjects”.

Implementation dependent: only in CLISP

The :DECLARE keyword is recognized as equivalent to the :DECLARATIONS keyword, for compatibility with ENSURE-GENERIC-FUNCTION in [ANSI CL].

Values
The result is a generic function metaobject.
Purpose

The generic function CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS is called to define or modify the definition of a globally named generic function. It is called by the ENSURE-GENERIC-FUNCTION function. It can also be called directly.

The first step performed by this generic function is to compute the set of initialization arguments which will be used to create or reinitialize the globally named generic function. These initialization arguments are computed from the full set of keyword arguments received by this generic function as follows:

  • The :GENERIC-FUNCTION-CLASS argument is not included in the initialization arguments.
  • If the :METHOD-CLASS argument was received by this generic function, it is converted into a class metaobject. This is done by looking up the class name with FIND-CLASS. If there is no such class, an ERROR is SIGNALed.
  • All other keyword arguments are included directly in the initialization arguments.

If the generic-function argument is NIL, an instance of the class specified by the :GENERIC-FUNCTION-CLASS argument is created by calling MAKE-INSTANCE with the previously computed initialization arguments. The function name function-name is set to name the generic function. The newly created generic function metaobject is returned.

If the class of the generic-function argument is not the same as the class specified by the :GENERIC-FUNCTION-CLASS argument, an ERROR is SIGNALed.

Implementation dependent: only in CLISP

The description of ENSURE-GENERIC-FUNCTION in [ANSI CL] specifies that in this case, CHANGE-CLASS is called if the class of the generic-function argument and the class specified by the :GENERIC-FUNCTION-CLASS argument are compatible. Given the description of ENSURE-GENERIC-FUNCTION, this also applies to the CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS function. CLISP's implementation calls CHANGE-CLASS always, and leaves it to the CHANGE-CLASS function to signal an error if needed.

Otherwise the generic function generic-function is redefined by calling the REINITIALIZE-INSTANCE generic function with generic-function and the initialization arguments. The generic-function argument is then returned.

Methods

(CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS (generic-function GENERIC-FUNCTION) function-name &KEY :GENERIC-FUNCTION-CLASS &ALLOW-OTHER-KEYS)

This method implements the behavior of the generic function in the case where function-name names an existing generic function.

This method can be overridden.

(CLOS:ENSURE-GENERIC-FUNCTION-USING-CLASS (generic-function NULL) function-name &KEY :GENERIC-FUNCTION-CLASS &ALLOW-OTHER-KEYS)
This method implements the behavior of the generic function in the case where function-name names no function, generic function, macro or special form.
29.1.5.4.4. Generic Function ADD-METHOD
Syntax
(ADD-METHOD generic-function method)
Arguments
Values
The generic-function argument is returned.
Purpose

This generic function associates an unattached method with a generic function.

An ERROR is SIGNALed if the lambda list of the method is not congruent with the lambda list of the generic function.

An ERROR is SIGNALed if the method is already associated with some other generic function.

If the given method agrees with an existing method of the generic function on parameter specializers and qualifiers, the existing method is removed by calling REMOVE-METHOD before the new method is added. See the [ANSI CL] section 7.6.3 “Agreement on Parameter Specializers and Qualifiers for a definition of agreement in this context.

Associating the method with the generic function then proceeds in four steps:

  1. add method to the set returned by CLOS:GENERIC-FUNCTION-METHODS and arrange for CLOS:METHOD-GENERIC-FUNCTION to return generic-function;
  2. call CLOS:ADD-DIRECT-METHOD for each of the method's specializers;
  3. call CLOS:COMPUTE-DISCRIMINATING-FUNCTION and install its result with CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION; and
  4. update the dependents of the generic function.

The generic function ADD-METHOD can be called by the user or the implementation.

Methods

(ADD-METHOD (generic-function STANDARD-GENERIC-FUNCTION) (method STANDARD-METHOD))
No behavior is specified for this method beyond that which is specified for the generic function.
(ADD-METHOD (generic-function STANDARD-GENERIC-FUNCTION) (method METHOD))
This method is specified by [ANSI CL].
29.1.5.4.5. Generic Function REMOVE-METHOD
Syntax
(REMOVE-METHOD generic-function method)
Arguments
Values
The generic-function argument is returned.
Purpose

This generic function breaks the association between a generic function and one of its methods.

No ERROR is SIGNALed if the method is not among the methods of the generic function.

Breaking the association between the method and the generic function proceeds in four steps:

  1. remove method from the set returned by CLOS:GENERIC-FUNCTION-METHODS and arrange for CLOS:METHOD-GENERIC-FUNCTION to return NIL;
  2. call CLOS:REMOVE-DIRECT-METHOD for each of the method's specializers;
  3. call CLOS:COMPUTE-DISCRIMINATING-FUNCTION and install its result with CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION; and
  4. update the dependents of the generic function.

The generic function REMOVE-METHOD can be called by the user or the implementation.

Methods

(REMOVE-METHOD (generic-function STANDARD-GENERIC-FUNCTION) (method STANDARD-METHOD))
No behavior is specified for this method beyond that which is specified for the generic function.
(REMOVE-METHOD (generic-function STANDARD-GENERIC-FUNCTION) (method METHOD))
This method is specified by [ANSI CL].
29.1.5.4.6. Generic Function CLOS:COMPUTE-APPLICABLE-METHODS
Syntax
(CLOS:COMPUTE-APPLICABLE-METHODS generic-function arguments)
Arguments
generic-function
a generic function metaobject.
arguments
a list of objects.
Values
This generic function returns a possibly empty list of method metaobjects.
Purpose

This generic function determines the method applicability of a generic function given a list of required arguments. The returned list of method metaobjects is sorted by precedence order with the most specific method appearing first. If no methods are applicable to the supplied arguments the empty list is returned.

When a generic function is invoked, the discriminating function must determine the ordered list of methods applicable to the arguments. Depending on the generic function and the arguments, this is done in one of three ways: using a memoized value; calling CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES; or calling CLOS:COMPUTE-APPLICABLE-METHODS. (Refer to the description of CLOS:COMPUTE-DISCRIMINATING-FUNCTION for the details of this process.)

The arguments argument is permitted to contain more elements than the generic function accepts required arguments; in these cases the extra arguments will be ignored. An ERROR is SIGNALed if arguments contains fewer elements than the generic function accepts required arguments.

The list returned by this function will not be mutated by the implementation. The results are undefined if a portable program mutates the list returned by this function.

Methods

(CLOS:COMPUTE-APPLICABLE-METHODS (generic-function STANDARD-GENERIC-FUNCTION) arguments)

This method SIGNALs an ERROR if any method of the generic function has a specializer which is neither a class metaobject nor an EQL specializer metaobject.

Otherwise, this method computes the sorted list of applicable methods according to the rules described in the [ANSI CL] section 7.6.6 “Method Selection and Combination

This method can be overridden. Because of the consistency requirements between this generic function and CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES, doing so may require also overriding CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES (STANDARD-GENERIC-FUNCTION T).

Remarks.  See also the [ANSI CL] function COMPUTE-APPLICABLE-METHODS.

29.1.5.4.7. Generic Function CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES
Syntax
(CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES generic-function classes)
Arguments
generic-function
a generic function metaobject.
classes
a list of class metaobjects.
Values
This generic function returns two values. The first is a possibly empty list of method metaobjects. The second is either true or false.
Purpose

This generic function is called to attempt to determine the method applicability of a generic function given only the classes of the required arguments.

If it is possible to completely determine the ordered list of applicable methods based only on the supplied classes, this generic function returns that list as its primary value and true as its second value. The returned list of method metaobjects is sorted by precedence order, the most specific method coming first. If no methods are applicable to arguments with the specified classes, the empty list and true are returned.

If it is not possible to completely determine the ordered list of applicable methods based only on the supplied classes, this generic function returns an unspecified primary value and false as its second value.

When a generic function is invoked, the discriminating function must determine the ordered list of methods applicable to the arguments. Depending on the generic function and the arguments, this is done in one of three ways: using a memoized value; calling CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES; or calling CLOS:COMPUTE-APPLICABLE-METHODS. (Refer to the description of CLOS:COMPUTE-DISCRIMINATING-FUNCTION for the details of this process.)

The following consistency relationship between CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES and CLOS:COMPUTE-APPLICABLE-METHODS must be maintained: for any given generic function and set of arguments, if CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES returns a second value of true, the primary value must be equal to the value that would be returned by a corresponding call to CLOS:COMPUTE-APPLICABLE-METHODS. The results are undefined if a portable method on either of these generic functions causes this consistency to be violated.

The list returned by this function will not be mutated by the implementation. The results are undefined if a portable program mutates the list returned by this function.

Methods

(CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES (generic-function STANDARD-GENERIC-FUNCTION) classes)

If any method of the generic function has a specializer which is neither a class metaobject nor an EQL specializer metaobject, this method SIGNALs an ERROR.

In cases where the generic function has no methods with EQL specializers, or has no methods with EQL specializers that could be applicable to arguments of the supplied classes, this method returns the ordered list of applicable methods as its first value and true as its second value.

Otherwise this method returns an unspecified primary value and false as its second value.

This method can be overridden. Because of the consistency requirements between this generic function and CLOS:COMPUTE-APPLICABLE-METHODS, doing so may require also overriding CLOS:COMPUTE-APPLICABLE-METHODS (STANDARD-GENERIC-FUNCTION T) .

Remarks

This generic function exists to allow user extensions which alter method lookup rules, but which base the new rules only on the classes of the required arguments, to take advantage of the class-based method lookup memoization found in many implementations. (There is of course no requirement for an implementation to provide this optimization.)

Such an extension can be implemented by two methods, one on this generic function and one on CLOS:COMPUTE-APPLICABLE-METHODS. Whenever the user extension is in effect, the first method will return a second value of true. This should allow the implementation to absorb these cases into its own memoization scheme.

To get appropriate performance, other kinds of extensions may require methods on CLOS:COMPUTE-DISCRIMINATING-FUNCTION which implement their own memoization scheme.

29.1.5.4.8. Generic Function CLOS:COMPUTE-EFFECTIVE-METHOD
Syntax
(CLOS:COMPUTE-EFFECTIVE-METHOD generic-function method-combination methods)
Arguments
generic-function
a generic function metaobject.
method-combination
a method combination metaobject.
methods
a list of method metaobjects.
Values
This generic function returns two values. The first is an effective method, the second is a list of effective method options.
Purpose

This generic function is called to determine the effective method from a sorted list of method metaobjects.

An effective method is a form that describes how the applicable methods are to be combined. Inside of effective method forms are CALL-METHOD forms which indicate that a particular method is to be called. The arguments to the CALL-METHOD form indicate exactly how the method function of the method should be called. (See CLOS:MAKE-METHOD-LAMBDA for more details about method functions.)

An effective method option has the same interpretation and syntax as either the :ARGUMENTS or the :GENERIC-FUNCTION option in the long form of DEFINE-METHOD-COMBINATION.

More information about the form and interpretation of effective methods and effective method options can be found under the description of the DEFINE-METHOD-COMBINATION macro in the CLOS specification.

This generic function can be called by the user or the implementation. It is called by discriminating functions whenever a sorted list of applicable methods must be converted to an effective method.

Methods

(CLOS:COMPUTE-EFFECTIVE-METHOD (generic-function STANDARD-GENERIC-FUNCTION) method-combination methods)

This method computes the effective method according to the rules of the method combination type implemented by method-combination.

This method can be overridden.

Implementation dependent: only in CLISP

The second return value may contain only one :ARGUMENTS option and only one :GENERIC-FUNCTION option. When overriding a CLOS:COMPUTE-EFFECTIVE-METHOD method, before adding an :ARGUMENTS or :GENERIC-FUNCTION option, you therefore need to check whether it this option is already present.

Implementation dependent: only in CLISP

Syntax
(CLOS:COMPUTE-EFFECTIVE-METHOD-AS-FUNCTION generic-function methods arguments)
Arguments
generic-function
a generic function metaobject.
methods
a list of method metaobjects.
arguments
a list of arguments.
Values
This function returns the effective method as a function, accepting any set of arguments for which all of the given methods are applicable.
Purpose

This function is called to determine the effective method from a sorted list of method metaobjects, and convert it to a function. The arguments are a set of arguments to which the methods are applicable, and are used solely for error message purposes.

This function calls CLOS:COMPUTE-EFFECTIVE-METHOD using the generic-function's method combination, wraps local macro definitions for CALL-METHOD and MAKE-METHOD around it, handles the :ARGUMENTS and :GENERIC-FUNCTION options, and compiles the resulting form to a function.

29.1.5.4.10. Generic Function CLOS:MAKE-METHOD-LAMBDA
Syntax
(CLOS:MAKE-METHOD-LAMBDA generic-function method lambda-expression environment)
Arguments
generic-function
a generic function metaobject.
method
a (possibly uninitialized) method metaobject.
lambda-expression
a lambda expression.
environment
the same as the &ENVIRONMENT argument to macro expansion functions.
Values
This generic function returns two values. The first is a lambda expression, the second is a list of initialization arguments and values.
Purpose

This generic function is called to produce a lambda expression which can itself be used to produce a method function for a method and generic function with the specified classes. The generic function and method the method function will be used with are not required to be the given ones. Moreover, the method metaobject may be uninitialized.

Either the function COMPILE, the special form FUNCTION or the function COERCE must be used to convert the lambda expression a method function. The method function itself can be applied to arguments with APPLY or FUNCALL.

When a method is actually called by an effective method, its first argument will be a list of the arguments to the generic function. Its remaining arguments will be all but the first argument passed to CALL-METHOD. By default, all method functions must accept two arguments: the list of arguments to the generic function and the list of next methods.

For a given generic function and method class, the applicable methods on CLOS:MAKE-METHOD-LAMBDA and CLOS:COMPUTE-EFFECTIVE-METHOD must be consistent in the following way: each use of CALL-METHOD returned by the method on CLOS:COMPUTE-EFFECTIVE-METHOD must have the same number of arguments, and the method lambda returned by the method on CLOS:MAKE-METHOD-LAMBDA must accept a corresponding number of arguments.

Note that the system-supplied implementation of CALL-NEXT-METHOD is not required to handle extra arguments to the method function. Users who define additional arguments to the method function must either redefine or forego CALL-NEXT-METHOD. (See the example below.)

When the method metaobject is created with MAKE-INSTANCE, the method function must be the value of the :FUNCTION initialization argument. The additional initialization arguments, returned as the second value of this generic function, must also be passed in this call to MAKE-INSTANCE.

Methods

(CLOS:MAKE-METHOD-LAMBDA (generic-function STANDARD-GENERIC-FUNCTION) (method STANDARD-METHOD) lambda-expression environment)

This method returns a method lambda which accepts two arguments, the list of arguments to the generic function, and the list of next methods. What initialization arguments may be returned in the second value are unspecified.

This method can be overridden.

This example shows how to define a kind of method which, from within the body of the method, has access to the actual method metaobject for the method. This simplified code overrides whatever method combination is specified for the generic function, implementing a simple method combination supporting only primary methods, CALL-NEXT-METHOD and NEXT-METHOD-P. (In addition, its a simplified version of CALL-NEXT-METHOD which does no error checking.)

Notice that the extra lexical function bindings get wrapped around the body before CALL-NEXT-METHOD is called. In this way, the user's definition of CALL-NEXT-METHOD and NEXT-METHOD-P are sure to override the system's definitions.

(defclass my-generic-function (standard-generic-function)
  ()
  (:default-initargs :method-class (find-class 'my-method)))

(defclass my-method (standard-method) ())

(defmethod make-method-lambda ((gf my-generic-function)
                               (method my-method)
                               lambda-expression
                               environment)
  (declare (ignore environment))
  `(lambda (args next-methods this-method)
     (,(call-next-method gf method
         `(lambda ,(cadr lambda-expression)
            (flet ((this-method () this-method)
                   (call-next-method (&REST cnm-args)
                     (funcall (method-function (car next-methods))
                              (or cnm-args args)
                              (cdr next-methods)
                              (car next-methods)))
                   (next-method-p ()
                     (not (null next-methods))))
              ,@(cddr lambda-expression)))
          environment)
       args next-methods)))

(defmethod compute-effective-method ((gf my-generic-function)
                                     method-combination
                                     methods)
  `(call-method ,(car methods) ,(cdr methods) ,(car methods)))

Implementation dependent: only in CLISP

The generic function CLOS:MAKE-METHOD-LAMBDA is not implemented. Its specification is misdesigned: it mixes compile time and execution time behaviour. The essential problem is: where could the generic-function argument come from?

  • If a DEFMETHOD form occurs in a source file, is CLOS:MAKE-METHOD-LAMBDA then called at compile time or at load time? If it was called at compile time, there's no possible value for the first argument, since the class of the generic function to which the method will belong is not known until load time. If it was called at load time, it would mean that the method's source code could only be compiled at load time, not earlier - which defeats the purpose of COMPILE-FILE
  • When a method is removed from a generic function using REMOVE-METHOD and then added through ADD-METHOD to a different generic function, possibly belonging to a different generic function class, would CLOS:MAKE-METHOD-LAMBDA then be called again or not? If no, then CLOS:MAKE-METHOD-LAMBDA's first argument is useless. If yes, then the source code of every method would have to be present at runtime, and its lexical environment as well.

Method function arguments. 

  • CALL-METHOD always expect exactly two arguments: the method and a list of next methods.
  • Method functions always expect exactly two arguments: the list of arguments passed to the generic function, and the list of next methods.
29.1.5.4.11. Generic Function CLOS:COMPUTE-DISCRIMINATING-FUNCTION
Syntax
(CLOS:COMPUTE-DISCRIMINATING-FUNCTION generic-function)
Arguments
generic-function
a generic function metaobject.
Values
The value returned by this generic function is a function.
Purpose

This generic function is called to determine the discriminating function for a generic function. When a generic function is called, the installed discriminating function is called with the full set of arguments received by the generic function, and must implement the behavior of calling the generic function: determining the ordered set of applicable methods, determining the effective method, and running the effective method.

To determine the ordered set of applicable methods, the discriminating function first calls CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES. If CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES returns a second value of false, the discriminating function then calls CLOS:COMPUTE-APPLICABLE-METHODS.

When CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES returns a second value of true, the discriminating function is permitted to memoize the primary value as follows. The discriminating function may reuse the list of applicable methods without calling CLOS:COMPUTE-APPLICABLE-METHODS-USING-CLASSES again provided that:

  1. the generic function is being called again with required arguments which are instances of the same classes,
  2. the generic function has not been reinitialized,
  3. no method has been added to or removed from the generic function,
  4. for all the specializers of all the generic function's methods which are classes, their class precedence lists have not changed, and
  5. for any such memoized value, the class precedence list of the class of each of the required arguments has not changed.

Determination of the effective method is done by calling CLOS:COMPUTE-EFFECTIVE-METHOD. When the effective method is run, each method's function is called, and receives as arguments:

  1. a list of the arguments to the generic function,
  2. whatever other arguments are specified in the CALL-METHOD form indicating that the method should be called.

(See CLOS:MAKE-METHOD-LAMBDA for more information about how method functions are called.)

The generic function CLOS:COMPUTE-DISCRIMINATING-FUNCTION is called, and its result installed, by ADD-METHOD, REMOVE-METHOD, INITIALIZE-INSTANCE and REINITIALIZE-INSTANCE.

Methods

(CLOS:COMPUTE-DISCRIMINATING-FUNCTION (generic-function STANDARD-GENERIC-FUNCTION))

No behavior is specified for this method beyond that which is specified for the generic function.

This method can be overridden.

Implementation dependent: only in CLISP

Overriding methods can make use of the function CLOS:COMPUTE-EFFECTIVE-METHOD-AS-FUNCTION. It is more convenient to call CLOS:COMPUTE-EFFECTIVE-METHOD-AS-FUNCTION than CLOS:COMPUTE-EFFECTIVE-METHOD because the in the latter case one needs a lot of “glue code” for implementing the local macros CALL-METHOD and MAKE-METHOD, and this glue code is implementation dependent because it needs

  1. to retrieve the declarations list stored in the method-combination object and
  2. to handle implementation dependent options that are returned as second value from CLOS:COMPUTE-EFFECTIVE-METHOD.

29.1.6. Methods

29.1.6.1. Inheritance Structure of method metaobject Classes

Figure 29.5. Inheritance structure of method metaobject classes

Inheritance structure of method metaobject classes

29.1.6.2. Introspection: Readers for method metaobjects

The reader generic functions which simply return information associated with method metaobjects are presented together here in the format described in Section 29.1.3.3, “Introspection: Readers for class metaobjects”.

Each of these reader generic functions have the same syntax, accepting one required argument called method, which must be a method metaobject; otherwise, an ERROR is SIGNALed. An ERROR is also SIGNALed if the method metaobject has not been initialized.

These generic functions can be called by the user or the implementation.

For any of these generic functions which returns a list, such lists will not be mutated by the implementation. The results are undefined if a portable program allows such a list to be mutated.

29.1.6.2.1. Generic Function CLOS:METHOD-SPECIALIZERS

Returns a list of the specializers of method. This value is a list of specializer metaobjects. This is the value of the :SPECIALIZERS initialization argument that was associated with the method during initialization.

29.1.6.2.2. Generic Function METHOD-QUALIFIERS

Returns a (possibly empty) list of the qualifiers of method. This value is a list of non-NIL atoms. This is the defaulted value of the :QUALIFIERS initialization argument that was associated with the method during initialization.

29.1.6.2.3. Generic Function CLOS:METHOD-LAMBDA-LIST

Returns the (unspecialized) lambda list of method. This value is a Common Lisp lambda list. This is the value of the :LAMBDA-LIST initialization argument that was associated with the method during initialization.

29.1.6.2.4. Generic Function CLOS:METHOD-GENERIC-FUNCTION

Returns the generic function that method is currently connected to, or NIL if it is not currently connected to any generic function. This value is either a generic function metaobject or NIL. When a method is first created it is not connected to any generic function. This connection is maintained by the generic functions ADD-METHOD and REMOVE-METHOD.

29.1.6.2.5. Generic Function CLOS:METHOD-FUNCTION

Returns the method function of method. This is the value of the :FUNCTION initialization argument that was associated with the method during initialization.

29.1.6.2.6. Methods

The specified methods for the method metaobject readers

(CLOS:METHOD-SPECIALIZERS (method STANDARD-METHOD))
(METHOD-QUALIFIERS (method STANDARD-METHOD))
(CLOS:METHOD-LAMBDA-LIST (method STANDARD-METHOD))
(CLOS:METHOD-FUNCTION (method STANDARD-METHOD))
No behavior is specified for these methods beyond that which is specified for their respective generic functions.
(CLOS:METHOD-GENERIC-FUNCTION (method STANDARD-METHOD))

No behavior is specified for this method beyond that which is specified for the generic function.

The value returned by this method is maintained by ADD-METHOD(STANDARD-GENERIC-FUNCTION STANDARD-METHOD) and REMOVE-METHOD(STANDARD-GENERIC-FUNCTION STANDARD-METHOD).

29.1.6.3. Initialization of Methods

29.1.6.3.1. Macro DEFMETHOD

The evaluation or execution of a DEFMETHOD form requires first that the body of the method be converted to a method function. This process is described below. The result of this process is a method function and a set of additional initialization arguments to be used when creating the new method. Given these two values, the evaluation or execution of a DEFMETHOD form proceeds in three steps.

The first step ensures the existence of a generic function with the specified name. This is done by calling the function ENSURE-GENERIC-FUNCTION. The first argument in this call is the generic function name specified in the DEFMETHOD form.

The second step is the creation of the new method metaobject by calling MAKE-INSTANCE. The class of the new method metaobject is determined by calling CLOS:GENERIC-FUNCTION-METHOD-CLASS on the result of the call to ENSURE-GENERIC-FUNCTION from the first step.

The initialization arguments received by the call to MAKE-INSTANCE are as follows:

  • The value of the :QUALIFIERS initialization argument is a list of the qualifiers which appeared in the DEFMETHOD form. No special processing is done on these values. The order of the elements of this list is the same as in the DEFMETHOD form.
  • The value of the :LAMBDA-LIST initialization argument is the unspecialized lambda list from the DEFMETHOD form.
  • The value of the :SPECIALIZERS initialization argument is a list of the specializers for the method. For specializers which are classes, the specializer is the class metaobject itself. In the case of EQL specializers, it will be an CLOS:EQL-SPECIALIZER metaobject obtained by calling CLOS:INTERN-EQL-SPECIALIZER on the result of evaluating the EQL specializer form in the lexical environment of the DEFMETHOD form.
  • The value of the :FUNCTION initialization argument is the method function.
  • The value of the :DECLARATIONS initialization argument is a list of the declaration specifiers from the DEFMETHOD form. If there are no declarations in the macro form, this initialization argument either does not appear, or appears with a value of the empty list.

    Implementation dependent: only in CLISP

    No :DECLARATIONS initialization argument is provided, because method initialization does not support a :DECLARATIONS argument, and because the method function is already completely provided through the :FUNCTION initialization argument.

  • The value of the :DOCUMENTATION initialization argument is the documentation string from the DEFMETHOD form. If there is no documentation string in the macro form this initialization argument either does not appear, or appears with a value of false.
  • Any other initialization argument produced in conjunction with the method function are also included.
  • The implementation is free to include additional initialization arguments provided these are not symbols accessible in the COMMON-LISP-USER package, or exported by any package defined in the [ANSI CL].

In the third step, ADD-METHOD is called to add the newly created method to the set of methods associated with the generic function metaobject.

The result of the call to ADD-METHOD is returned as the result of evaluating or executing the DEFMETHOD form.

An example showing a typical DEFMETHOD form and a sample expansion is shown in the following example:

An example DEFMETHOD form and one possible correct expansion. In the expansion, method-lambda is the result of calling CLOS:MAKE-METHOD-LAMBDA as described in Section 29.1.6.3.1.1, “Processing Method Bodies”. The initargs appearing after :FUNCTION are assumed to be additional initargs returned from the call to CLOS:MAKE-METHOD-LAMBDA.

(defmethod move :before ((p position) (l (eql 0))
                         &OPTIONAL (visiblyp t)
                         &KEY color)
  (set-to-origin p)
  (when visiblyp (show-move p 0 color)))

(let ((#:g001 (ensure-generic-function 'move)))
  (add-method #:g001
    (make-instance (generic-function-method-class #:g001)
                   :qualifiers '(:before)
                   :specializers (list (find-class 'position)
                                       (intern-eql-specializer 0))
                   :lambda-list '(p l &OPTIONAL (visiblyp t)
                                      &KEY color)
                   :function (function method-lambda)
                   'additional-initarg-1 't
                   'additional-initarg-2 '39)))

The processing of the method body for this method is shown below.

29.1.6.3.1.1. Processing Method Bodies

Before a method can be created, the list of forms comprising the method body must be converted to a method function. This conversion is a two step process.

Note

The body of methods can also appear in the :METHOD option of DEFGENERIC forms. Initial methods are not considered by any of the protocols specified in this document.

During macro-expansion of the DEFMETHOD macro shown in the previous example code similar to this would be run to produce the method lambda and additional initargs. In this example, environment is the macroexpansion environment of the DEFMETHOD macro form.

(let ((gf (ensure-generic-function 'move)))
  (make-method-lambda
    gf
    (class-prototype (generic-function-method-class gf))
    '(lambda (p l &OPTIONAL (visiblyp t) &KEY color)
       (set-to-origin p)
       (when visiblyp (show-move p 0 color)))
    environment))

The first step occurs during macro-expansion of the macro form. In this step, the method lambda list, declarations and body are converted to a lambda expression called a method lambda. This conversion is based on information associated with the generic function definition in effect at the time the macro form is expanded.

The generic function definition is obtained by calling ENSURE-GENERIC-FUNCTION with a first argument of the generic function name specified in the macro form. The :LAMBDA-LIST keyword argument is not passed in this call.

Given the generic function, production of the method lambda proceeds by calling CLOS:MAKE-METHOD-LAMBDA. The first argument in this call is the generic function obtained as described above. The second argument is the result of calling CLOS:CLASS-PROTOTYPE on the result of calling CLOS:GENERIC-FUNCTION-METHOD-CLASS on the generic function. The third argument is a lambda expression formed from the method lambda list, declarations and body. The fourth argument is the macro-expansion environment of the macro form; this is the value of the &ENVIRONMENT argument to the DEFMETHOD macro.

The generic function CLOS:MAKE-METHOD-LAMBDA returns two values. The first is the method lambda itself. The second is a list of initialization arguments and values. These are included in the initialization arguments when the method is created.

In the second step, the method lambda is converted to a function which properly captures the lexical scope of the macro form. This is done by having the method lambda appear in the macro-expansion as the argument of the FUNCTION special form. During the subsequent evaluation of the macro-expansion, the result of the FUNCTION special form is the method function.

Implementation dependent: only in CLISP

See The generic function CLOS:MAKE-METHOD-LAMBDA is not implemented.

29.1.6.3.1.2. Initialization of Generic Function and method metaobjects

An example of creating a generic function and a method metaobject, and then adding the method to the generic function is shown below. This example is comparable to the method definition shown above:

(let* ((gf (make-instance 'standard-generic-function
                          :lambda-list '(p l &OPTIONAL visiblyp &KEY)))
       (method-class (generic-function-method-class gf)))
  (multiple-value-bind (lambda initargs)
       (make-method-lambda
         gf
         (class-prototype method-class)
         '(lambda (p l &OPTIONAL (visiblyp t) &KEY color)
            (set-to-origin p)
            (when visiblyp (show-move p 0 color)))
         nil)
    (add-method gf
                (apply #'make-instance method-class
                       :function (compile nil lambda)
                       :specializers (list (find-class 'position)
                                           (intern-eql-specializer 0))
                       :qualifiers ()
                       :lambda-list '(p l &OPTIONAL (visiblyp t)
                                          &KEY color)
                       initargs))))
29.1.6.3.1.3. Efficiency
Implementation dependent: only in CLISP and some other implementations

Methods created through DEFMETHOD have a faster calling convention than methods created through a portable MAKE-INSTANCE invocation.

29.1.6.3.2. Initialization of method metaobjects

A method metaobject can be created by calling MAKE-INSTANCE. The initialization arguments establish the definition of the method. A method metaobject cannot be redefined; calling REINITIALIZE-INSTANCE SIGNALs an ERROR.

Initialization of a method metaobject must be done by calling MAKE-INSTANCE and allowing it to call INITIALIZE-INSTANCE. Portable programs must not

Since metaobject classes may not be redefined, no behavior is specified for the result of calls to UPDATE-INSTANCE-FOR-REDEFINED-CLASS on method metaobjects. Since the class of a method metaobject cannot be changed, no behavior is specified for the result of calls to UPDATE-INSTANCE-FOR-DIFFERENT-CLASS on method metaobjects.

During initialization, each initialization argument is checked for errors and then associated with the method metaobject. The value can then be accessed by calling the appropriate accessor as shown in Table 29.5, “Initialization arguments and accessors for method metaobjects”.

This section begins with a description of the error checking and processing of each initialization argument. This is followed by a table showing the generic functions that can be used to access the stored initialization arguments. The section ends with a set of restrictions on portable methods affecting method metaobject initialization.

In these descriptions, the phrase “this argument defaults to value” means that when that initialization argument is not supplied, initialization is performed as if value had been supplied. For some initialization arguments this could be done by the use of default initialization arguments, but whether it is done this way is not specified. Implementations are free to define default initialization arguments for specified method metaobject classes. Portable programs are free to define default initialization arguments for portable subclasses of the class METHOD.

  • The :QUALIFIERS argument is a list of method qualifiers. An ERROR is SIGNALed if this value is not a proper list, or if any element of the list is not a non-null atom. This argument defaults to the empty list.
  • The :LAMBDA-LIST argument is the unspecialized lambda list of the method. An ERROR is SIGNALed if this value is not a proper lambda list. If this value is not supplied, an ERROR is SIGNALed.
  • The :SPECIALIZERS argument is a list of the specializer metaobjects for the method. An ERROR is SIGNALed if this value is not a proper list, or if the length of the list differs from the number of required arguments in the :LAMBDA-LIST argument, or if any element of the list is not a specializer metaobject. If this value is not supplied, an ERROR is SIGNALed.
  • The :FUNCTION argument is a method function. It must be compatible with the methods on CLOS:COMPUTE-EFFECTIVE-METHOD defined for this class of method and generic function with which it will be used. That is, it must accept the same number of arguments as all uses of CALL-METHOD that will call it supply. (See CLOS:COMPUTE-EFFECTIVE-METHOD and CLOS:MAKE-METHOD-LAMBDA for more information.) An ERROR is SIGNALed if this argument is not supplied.
  • When the method being initialized is an instance of a subclass of CLOS:STANDARD-ACCESSOR-METHOD, the :SLOT-DEFINITION initialization argument must be provided. Its value is the direct slot definition metaobject which defines this accessor method. An ERROR is SIGNALed if the value is not an instance of a subclass of CLOS:DIRECT-SLOT-DEFINITION.
  • The :DOCUMENTATION argument is a string or NIL. An ERROR is SIGNALed if this value is not a string or NIL. This argument defaults to NIL.

After the processing and defaulting of initialization arguments described above, the value of each initialization argument is associated with the method metaobject. These values can then be accessed by calling the corresponding generic function. The correspondences are as follows:

Table 29.5. Initialization arguments and accessors for method metaobjects

Initialization ArgumentGeneric Function
:QUALIFIERSMETHOD-QUALIFIERS
:LAMBDA-LISTCLOS:METHOD-LAMBDA-LIST
:SPECIALIZERSCLOS:METHOD-SPECIALIZERS
:FUNCTIONCLOS:METHOD-FUNCTION
:SLOT-DEFINITIONCLOS:ACCESSOR-METHOD-SLOT-DEFINITION
:DOCUMENTATIONDOCUMENTATION


29.1.6.3.2.1. Methods

It is not specified which methods provide the initialization behavior described above. Instead, the information needed to allow portable programs to specialize this behavior is presented in as a set of restrictions on the methods a portable program can define. The model is that portable initialization methods have access to the method metaobject when either all or none of the specified initialization has taken effect.

These restrictions govern the methods that a portable program can define on the generic functions INITIALIZE-INSTANCE, REINITIALIZE-INSTANCE, and SHARED-INITIALIZE. These restrictions apply only to methods on these generic functions for which the first specializer is a subclass of the class METHOD. Other portable methods on these generic functions are not affected by these restrictions.

  • Portable programs must not define methods on SHARED-INITIALIZE or REINITIALIZE-INSTANCE.
  • For INITIALIZE-INSTANCE:

    • Portable programs must not define primary methods.
    • Portable programs may define around-methods, but these must be extending, not overriding methods.
    • Portable before-methods must assume that when they are run, none of the initialization behavior described above has been completed.
    • Portable after-methods must assume that when they are run, all of the initialization behavior described above has been completed.

The results are undefined if any of these restrictions are violated.

29.1.6.4. Customization

29.1.6.4.1. Function CLOS:EXTRACT-LAMBDA-LIST
Syntax
(CLOS:EXTRACT-LAMBDA-LIST specialized-lambda-list)
Arguments
specialized-lambda-list
a specialized lambda list as accepted by DEFMETHOD.
Values
The result is an unspecialized lambda list.
Purpose

This function takes a specialized lambda list and returns the lambda list with the specializers removed. This is a non-destructive operation. Whether the result shares any structure with the argument is unspecified.

If the specialized-lambda-list argument does not have legal syntax, an ERROR is SIGNALed. This syntax checking does not check the syntax of the actual specializer names, only the syntax of the lambda list and where the specializers appear.

Examples. 

(CLOS:EXTRACT-LAMBDA-LIST '((p position)))
⇒ (P)
(CLOS:EXTRACT-LAMBDA-LIST '((p position) x y))
⇒ (P X Y)
(CLOS:EXTRACT-LAMBDA-LIST '(a (b (eql x)) c &REST i))
⇒ (A B C &OPTIONAL I)
29.1.6.4.2. Function CLOS:EXTRACT-SPECIALIZER-NAMES
Syntax
(CLOS:EXTRACT-SPECIALIZER-NAMES specialized-lambda-list)
Arguments
specialized-lambda-list
a specialized lambda list as accepted by DEFMETHOD.
Values
The result is a list of specializer names.
Purpose

This function takes a specialized lambda list and returns its specializer names. This is a non-destructive operation. Whether the result shares structure with the argument is unspecified.

The list returned by this function will not be mutated by the implementation. The results are undefined if a portable program mutates the list returned by this function.

The result of this function will be a list with a number of elements equal to the number of required arguments in specialized-lambda-list. Specializers are defaulted to the symbol T.

If the specialized-lambda-list argument does not have legal syntax, an ERROR is SIGNALed. This syntax checking does not check the syntax of the actual specializer names, only the syntax of the lambda list and where the specializers appear.

Examples. 

(CLOS:EXTRACT-SPECIALIZER-NAMES '((p position)))
⇒ (POSITION)
(CLOS:EXTRACT-SPECIALIZER-NAMES '((p position) x y))
⇒ (POSITION T T)
(CLOS:EXTRACT-SPECIALIZER-NAMES '(a (b (eql x)) c &REST i))
⇒ (T (EQL X) T)

29.1.7. Accessor Methods

29.1.7.1. Introspection

This accessor can only be called on accessor methods. It returns the direct slot definition metaobject that defined this method. This is the value of the :SLOT-DEFINITION initialization argument associated with the method during initialization.

The specified methods for the accessor method metaobject readers

(CLOS:ACCESSOR-METHOD-SLOT-DEFINITION (method CLOS:STANDARD-ACCESSOR-METHOD))
No behavior is specified for this method beyond that which is specified for the generic function.

29.1.7.2. Customization

29.1.7.2.1. Generic Function CLOS:READER-METHOD-CLASS
Syntax
(CLOS:READER-METHOD-CLASS class direct-slot-definition &REST initargs)
Arguments
class
a class metaobject.
direct-slot-definition
a direct slot definition metaobject.
initargs
alternating initialization argument names and values.
Values
The value returned is a class metaobject.
Purpose

This generic function is called to determine the class of reader methods created during class initialization and reinitialization. The result must be a subclass of CLOS:STANDARD-READER-METHOD.

The initargs argument must be the same as will be passed to MAKE-INSTANCE to create the reader method. The initargs must include :SLOT-DEFINITION with slot-definition as its value.

Methods

(CLOS:READER-METHOD-CLASS (class STANDARD-CLASS) (direct-slot-definition CLOS:STANDARD-DIRECT-SLOT-DEFINITION) &REST initargs)
(CLOS:READER-METHOD-CLASS (class CLOS:FUNCALLABLE-STANDARD-CLASS) (direct-slot-definition CLOS:STANDARD-DIRECT-SLOT-DEFINITION) &REST initargs)

These methods return the class CLOS:STANDARD-READER-METHOD.

These methods can be overridden.

29.1.7.2.2. Generic Function CLOS:WRITER-METHOD-CLASS
Syntax
(CLOS:WRITER-METHOD-CLASS class direct-slot &REST initargs)
Arguments
class
a class metaobject.
direct-slot
a direct slot definition metaobject.
initargs
a list of initialization arguments and values.
Values
The value returned is a class metaobject.
Purpose

This generic function is called to determine the class of writer methods created during class initialization and reinitialization. The result must be a subclass of CLOS:STANDARD-WRITER-METHOD.

The initargs argument must be the same as will be passed to MAKE-INSTANCE to create the reader method. The initargs must include :SLOT-DEFINITION with CLOS:SLOT-DEFINITION as its value.

Methods

(CLOS:WRITER-METHOD-CLASS (class STANDARD-CLASS) (direct-slot CLOS:STANDARD-DIRECT-SLOT-DEFINITION) &REST initargs)
(CLOS:WRITER-METHOD-CLASS (class CLOS:FUNCALLABLE-STANDARD-CLASS) (direct-slot CLOS:STANDARD-DIRECT-SLOT-DEFINITION) &REST initargs)

These methods returns the class CLOS:STANDARD-WRITER-METHOD.

These methods can be overridden.

29.1.8. Specializers

29.1.8.1. Inheritance Structure of Specializer Metaobject Classes

Figure 29.6. Inheritance structure of specializer metaobject classes

Inheritance structure of specializer metaobject classes

29.1.8.2. Introspection

29.1.8.2.1. Function CLOS:EQL-SPECIALIZER-OBJECT
Syntax
(CLOS:EQL-SPECIALIZER-OBJECT eql-specializer)
Arguments
eql-specializer
an EQL specializer metaobject.
Values
The value returned by this function is an object.
Purpose

This function returns the object associated with eql-specializer during initialization. The value is guaranteed to be EQL to the value originally passed to CLOS:INTERN-EQL-SPECIALIZER, but it is not necessarily EQ to that value.

This function SIGNALs an ERROR if eql-specializer is not an EQL specializer.

29.1.8.3. Initialization

29.1.8.3.1. Function CLOS:INTERN-EQL-SPECIALIZER
Syntax
(CLOS:INTERN-EQL-SPECIALIZER object)
Arguments
object
any Lisp object.
Values
The result is the EQL specializer metaobject for object.
Purpose
This function returns the unique EQL specializer metaobject for object, creating one if necessary. Two calls to CLOS:INTERN-EQL-SPECIALIZER with EQL arguments will return the same (i.e., EQ) value.

Remarks. The result of calling CLOS:EQL-SPECIALIZER-OBJECT on the result of a call to CLOS:INTERN-EQL-SPECIALIZER is only guaranteed to be EQL to the original object argument, not necessarily EQ.

29.1.8.4. Updating Dependencies

29.1.8.4.1. Generic Function CLOS:SPECIALIZER-DIRECT-METHODS
Syntax
(CLOS:SPECIALIZER-DIRECT-METHODS specializer)
Arguments
specializer
a specializer metaobject.
Values
The result of this generic function is a possibly empty list of method metaobjects.
Purpose
This generic function returns the possibly empty set of those methods, connected to generic functions, which have specializer as a specializer. The elements of this set are method metaobjects. This value is maintained by the generic functions CLOS:ADD-DIRECT-METHOD and CLOS:REMOVE-DIRECT-METHOD.

Methods

(CLOS:SPECIALIZER-DIRECT-METHODS (specializer CLASS))

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:SPECIALIZER-DIRECT-METHODS (specializer CLOS:EQL-SPECIALIZER))
No behavior is specified for this method beyond that which is specified for the generic function.
29.1.8.4.2. Generic Function CLOS:SPECIALIZER-DIRECT-GENERIC-FUNCTIONS
Syntax
(CLOS:SPECIALIZER-DIRECT-GENERIC-FUNCTIONS specializer)
Arguments
specializer
a specializer metaobject.
Values
The result of this generic function is a possibly empty list of generic function metaobjects.
Purpose
This generic function returns the possibly empty set of those generic functions which have a method with specializer as a specializer. The elements of this set are generic function metaobjects. This value is maintained by the generic functions CLOS:ADD-DIRECT-METHOD and CLOS:REMOVE-DIRECT-METHOD.

Methods

(CLOS:SPECIALIZER-DIRECT-GENERIC-FUNCTIONS (specializer CLASS))

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:SPECIALIZER-DIRECT-GENERIC-FUNCTIONS (specializer CLOS:EQL-SPECIALIZER))
No behavior is specified for this method beyond that which is specified for the generic function.
29.1.8.4.3. Generic Function CLOS:ADD-DIRECT-METHOD
Syntax
(CLOS:ADD-DIRECT-METHOD specializer method)
Arguments
specializer
a specializer metaobject.
method
a method metaobject.
Values
The value returned by this generic function is unspecified.
Purpose

This generic function is called to maintain a set of backpointers from a specializer to the set of methods specialized to it. If method is already in the set, it is not added again (no ERROR is SIGNALed).

This set can be accessed as a list by calling the generic function CLOS:SPECIALIZER-DIRECT-METHODS. Methods are removed from the set by CLOS:REMOVE-DIRECT-METHOD.

The generic function CLOS:ADD-DIRECT-METHOD is called by ADD-METHOD whenever a method is added to a generic function. It is called once for each of the specializers of the method. Note that in cases where a specializer appears more than once in the specializers of a method, this generic function will be called more than once with the same specializer as argument.

The results are undefined if the specializer argument is not one of the specializers of the method argument.

Methods

(CLOS:ADD-DIRECT-METHOD (specializer CLASS) (method METHOD))

This method implements the behavior of the generic function for class specializers.

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-DIRECT-METHOD (specializer CLOS:EQL-SPECIALIZER) (method METHOD))

This method implements the behavior of the generic function for EQL specializers.

No behavior is specified for this method beyond that which is specified for the generic function.

29.1.8.4.4. Generic Function CLOS:REMOVE-DIRECT-METHOD
Syntax
(CLOS:REMOVE-DIRECT-METHOD specializer method)
Arguments
specializer
a specializer metaobject.
method
a method metaobject.
Values
The value returned by this generic function is unspecified.
Purpose

This generic function is called to maintain a set of backpointers from a specializer to the set of methods specialized to it. If method is in the set it is removed. If it is not, no ERROR is SIGNALed.

This set can be accessed as a list by calling the generic function CLOS:SPECIALIZER-DIRECT-METHODS. Methods are added to the set by CLOS:ADD-DIRECT-METHOD.

The generic function CLOS:REMOVE-DIRECT-METHOD is called by REMOVE-METHOD whenever a method is removed from a generic function. It is called once for each of the specializers of the method. Note that in cases where a specializer appears more than once in the specializers of a method, this generic function will be called more than once with the same specializer as argument.

The results are undefined if the specializer argument is not one of the specializers of the method argument.

Methods

(CLOS:REMOVE-DIRECT-METHOD (specializer CLASS) (method METHOD))

This method implements the behavior of the generic function for class specializers.

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-DIRECT-METHOD (specializer CLOS:EQL-SPECIALIZER) (method METHOD))

This method implements the behavior of the generic function for EQL specializers.

No behavior is specified for this method beyond that which is specified for the generic function.

29.1.9. Method Combinations

29.1.9.1. Inheritance Structure of method combination metaobject Classes

Figure 29.7. Inheritance structure of method combination metaobject classes

Inheritance structure of method combination metaobject classes

29.1.9.2. Customization

29.1.9.2.1. Generic Function CLOS:FIND-METHOD-COMBINATION
Syntax
(CLOS:FIND-METHOD-COMBINATION generic-function method-combination-type-name method-combination-options)
Arguments
generic-function
a generic function metaobject.
method-combination-type-name
a symbol which names a type of method combination.
method-combination-options
a list of arguments to the method combination type.
Values
The value returned by this generic function is a method combination metaobject.
Purpose
This generic function is called to determine the method combination object used by a generic function.

Remarks. Further details of method combination metaobjects are not specified.

29.1.10. Slot Access

29.1.10.1. Instance Structure Protocol

The instance structure protocol is responsible for implementing the behavior of the slot access functions like SLOT-VALUE and (SETF SLOT-VALUE).

For each CLOS slot access function other than SLOT-EXISTS-P, there is a corresponding generic function which actually provides the behavior of the function. When called, the slot access function finds the pertinent effective slot definition metaobject, calls the corresponding generic function and returns its result. The arguments passed on to the generic function include one additional value, the class of the object argument, which always immediately precedes the object argument.

Table 29.6. The correspondence between slot access function and underlying slot access generic function

Slot Access FunctionCorresponding Slot Access Generic Function
SLOT-VALUE object slot-nameCLOS:SLOT-VALUE-USING-CLASS class object slot
(SETF SLOT-VALUE) new-value object slot-name(SETF CLOS:SLOT-VALUE-USING-CLASS) new-value class object slot
SLOT-BOUNDP object slot-nameCLOS:SLOT-BOUNDP-USING-CLASS class object slot
SLOT-MAKUNBOUND object slot-nameCLOS:SLOT-MAKUNBOUND-USING-CLASS class object slot

At the lowest level, the instance structure protocol provides only limited mechanisms for portable programs to control the implementation of instances and to directly access the storage associated with instances without going through the indirection of slot access. This is done to allow portable programs to perform certain commonly requested slot access optimizations.

In particular, portable programs can control the implementation of, and obtain direct access to, slots with allocation :INSTANCE and type T. These are called directly accessible slots.

The relevant specified around-method on CLOS:COMPUTE-SLOTS determines the implementation of instances by deciding how each slot in the instance will be stored. For each directly accessible slot, this method allocates a location and associates it with the effective slot definition metaobject. The location can be accessed by calling the CLOS:SLOT-DEFINITION-LOCATION generic function. Locations are non-negative integers. For a given class, the locations increase consecutively, in the order that the directly accessible slots appear in the list of effective slots. (Note that here, the next paragraph, and the specification of this around-method are the only places where the value returned by CLOS:COMPUTE-SLOTS is described as a list rather than a set.)

Given the location of a directly accessible slot, the value of that slot in an instance can be accessed with the appropriate accessor. For STANDARD-CLASS, this accessor is the function CLOS:STANDARD-INSTANCE-ACCESS. For CLOS:FUNCALLABLE-STANDARD-CLASS, this accessor is the function CLOS:FUNCALLABLE-STANDARD-INSTANCE-ACCESS. In each case, the arguments to the accessor are the instance and the slot location, in that order. See the definition of each accessor for additional restrictions on the use of these function.

Portable programs are permitted to affect and rely on the allocation of locations only in the following limited way: By first defining a portable primary method on CLOS:COMPUTE-SLOTS which orders the returned value in a predictable way, and then relying on the defined behavior of the specified around-method to assign locations to all directly accessible slots. Portable programs may compile-in calls to low-level accessors which take advantage of the resulting predictable allocation of slot locations.

This example shows the use of this mechanism to implement a new class metaobject class, ordered-class and class option :SLOT-ORDER. This option provides control over the allocation of slot locations. In this simple example implementation, the :SLOT-ORDER option is not inherited by subclasses; it controls only instances of the class itself.

(defclass ordered-class (standard-class)
  ((slot-order :initform ()
               :initarg :slot-order
               :reader class-slot-order)))

(defmethod compute-slots ((class ordered-class))
  (let ((order (class-slot-order class)))
    (sort (copy-list (call-next-method))
          #'(lambda (a b)
              (< (position (slot-definition-name a) order)
                 (position (slot-definition-name a) order))))))

Following is the source code the user of this extension would write. Note that because the code above does not implement inheritance of the :SLOT-ORDER option, the function distance must not be called on instances of subclasses of point; it can only be called on instances of point itself.

(defclass point ()
  ((x :initform 0)
   (y :initform 0))
  (:metaclass ordered-class)
  (:slot-order x y))

(defun distance (point)
  (sqrt (/ (+ (expt (standard-instance-access point 0) 2)
              (expt (standard-instance-access point 1) 2))
           2.0)))

Implementation dependent: only in CLISP

You cannot assume that the slot-location values start at 0. In class point, for example, x and y will be at slot locations 1 and 2, not 0 and 1.

In more realistic uses of this mechanism, the calls to the low-level instance structure accessors would not actually appear textually in the source program, but rather would be generated by a meta-level analysis program run during the process of compiling the source program.

29.1.10.2. Funcallable Instances

Instances of classes which are themselves instances of CLOS:FUNCALLABLE-STANDARD-CLASS or one of its subclasses are called funcallable instances. Funcallable instances can only be created by ALLOCATE-INSTANCE (CLOS:FUNCALLABLE-STANDARD-CLASS).

Like standard instances, funcallable instances have slots with the normal behavior. They differ from standard instances in that they can be used as functions as well; that is, they can be passed to FUNCALL and APPLY, and they can be stored as the definition of a function name. Associated with each funcallable instance is the function which it runs when it is called. This function can be changed with CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION.

The following simple example shows the use of funcallable instances to create a simple, DEFSTRUCT-like facility. (Funcallable instances are useful when a program needs to construct and maintain a set of functions and information about those functions. They make it possible to maintain both as the same object rather than two separate objects linked, for example, by hash tables.)

(defclass constructor ()
  ((name :initarg :name :accessor constructor-name)
   (fields :initarg :fields :accessor constructor-fields))
  (:metaclass funcallable-standard-class))
⇒ #>FUNCALLABLE-STANDARD-CLASS CONSTRUCTOR>
(defmethod initialize-instance :after ((c constructor) &KEY)
  (with-slots (name fields) c
    (set-funcallable-instance-function
      c
      #'(lambda ()
          (let ((new (make-array (1+ (length fields)))))
            (setf (aref new 0) name)
            new)))))
⇒ #<STANDARD-METHOD :AFTER (#<FUNCALLABLE-STANDARD-CLASS CONSTRUCTOR>)>
(setq c1 (make-instance 'constructor :name 'position :fields '(x y)))
⇒ #<CONSTRUCTOR #<UNBOUND>>
(setq p1 (funcall c1))
⇒ #(POSITION NIL NIL)

29.1.10.3. Customization

29.1.10.3.1. Function CLOS:STANDARD-INSTANCE-ACCESS
Syntax
(CLOS:STANDARD-INSTANCE-ACCESS instance location)
Arguments
instance
an object
location
a slot location
Values
The result of this function is an object.
Purpose

This function is called to provide direct access to a slot in an instance. By usurping the normal slot lookup protocol, this function is intended to provide highly optimized access to the slots associated with an instance.

The following restrictions apply to the use of this function:

  • The instance argument must be a standard instance (it must have been returned by ALLOCATE-INSTANCE(STANDARD-CLASS)).
  • The instance argument cannot be an non-updated obsolete instance.
  • The location argument must be a location of one of the directly accessible slots of the instance's class.
  • The slot must be bound.

The results are undefined if any of these restrictions are violated.

Implementation dependent: only in CLISP

The second and third restrictions do not apply in CLISP. CLISP's implementation supports non-updated obsolete instances and also supports slots with allocation :CLASS.

Syntax
(CLOS:FUNCALLABLE-STANDARD-INSTANCE-ACCESS instance location)
Arguments
instance
an object
location
a slot location
Values
The result of this function is an object.
Purpose

This function is called to provide direct access to a slot in an instance. By usurping the normal slot lookup protocol, this function is intended to provide highly optimized access to the slots associated with an instance.

The following restrictions apply to the use of this function:

  • The instance argument must be a funcallable instance (it must have been returned by ALLOCATE-INSTANCE (CLOS:FUNCALLABLE-STANDARD-CLASS)).
  • The instance argument cannot be an non-updated obsolete instance.
  • The location argument must be a location of one of the directly accessible slots of the instance's class.
  • The slot must be bound.

The results are undefined if any of these restrictions are violated.

Implementation dependent: only in CLISP

The second and third restrictions do not apply in CLISP. CLISP's implementation supports non-updated obsolete instances and also supports slots with allocation :CLASS.

Syntax
(CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION funcallable-instance function)
Arguments
funcallable-instance
a funcallable instance (it must have been returned by ALLOCATE-INSTANCE (CLOS:FUNCALLABLE-STANDARD-CLASS)).
function
a function.
Values
The value returned by this generic function is unspecified.
Purpose
This function is called to set or to change the function of a funcallable instance. After CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION is called, any subsequent calls to funcallable-instance will run the new function.
29.1.10.3.4. Generic Function CLOS:SLOT-VALUE-USING-CLASS
Syntax
(CLOS:SLOT-VALUE-USING-CLASS class object slot)
Arguments
class
a class metaobject - the class of the object argument
object
an object
slot
an effective slot definition metaobject
Values
The value returned by this generic function is an object.
Purpose

This generic function implements the behavior of the SLOT-VALUE function. It is called by SLOT-VALUE with the class of object as its first argument and the pertinent effective slot definition metaobject as its third argument.

The generic function CLOS:SLOT-VALUE-USING-CLASS returns the value contained in the given slot of the given object. If the slot is unbound, SLOT-UNBOUND is called.

The results are undefined if the class argument is not the class of the object argument, or if the slot argument does not appear among the set of effective slots associated with the class argument.

Methods

(CLOS:SLOT-VALUE-USING-CLASS (class STANDARD-CLASS) object (slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))
(CLOS:SLOT-VALUE-USING-CLASS (class CLOS:FUNCALLABLE-STANDARD-CLASS) object (slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))

These methods implement the full behavior of this generic function for slots with allocation :INSTANCE and :CLASS. If the supplied slot has an allocation other than :INSTANCE or :CLASS an ERROR is SIGNALed.

Overriding these methods is permitted, but may require overriding other methods in the standard implementation of the slot access protocol.

(CLOS:SLOT-VALUE-USING-CLASS (class BUILT-IN-CLASS) object slot)
This method SIGNALs an ERROR.
29.1.10.3.5. Generic Function (SETF CLOS:SLOT-VALUE-USING-CLASS)
Syntax
((SETF CLOS:SLOT-VALUE-USING-CLASS) new-value class object slot)
Arguments
new-value
an object
class
a class metaobject - the class of the object argument.
object
an object
slot
an effective slot definition metaobject.
Values
This generic function returns the new-value argument.
Purpose

The generic function (SETF CLOS:SLOT-VALUE-USING-CLASS) implements the behavior of the (SETF SLOT-VALUE) function. It is called by (SETF SLOT-VALUE) with the class of object as its second argument and the pertinent effective slot definition metaobject as its fourth argument.

The generic function (SETF CLOS:SLOT-VALUE-USING-CLASS) sets the value contained in the given slot of the given object to the given new value; any previous value is lost.

The results are undefined if the class argument is not the class of the object argument, or if the slot argument does not appear among the set of effective slots associated with the class argument.

Methods

((SETF CLOS:SLOT-VALUE-USING-CLASS) new-value (class STANDARD-CLASS) object (slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))
((SETF CLOS:SLOT-VALUE-USING-CLASS) new-value (class CLOS:FUNCALLABLE-STANDARD-CLASS) object (slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))

These methods implement the full behavior of this generic function for slots with allocation :INSTANCE and :CLASS. If the supplied slot has an allocation other than :INSTANCE or :CLASS an ERROR is SIGNALed.

Overriding these methods is permitted, but may require overriding other methods in the standard implementation of the slot access protocol.

((SETF CLOS:SLOT-VALUE-USING-CLASS) new-value (class BUILT-IN-CLASS) object slot)
This method SIGNALs an ERROR.
29.1.10.3.6. Generic Function CLOS:SLOT-BOUNDP-USING-CLASS
Syntax
(CLOS:SLOT-BOUNDP-USING-CLASS class object slot)
Arguments
class
a class metaobject - the class of the object argument.
object
an object
slot
an effective slot definition metaobject.
Values
This generic function returns true or false.
Purpose

This generic function implements the behavior of the SLOT-BOUNDP function. It is called by SLOT-BOUNDP with the class of object as its first argument and the pertinent effective slot definition metaobject as its third argument.

The generic function CLOS:SLOT-BOUNDP-USING-CLASS tests whether a specific slot in an instance is bound.

The results are undefined if the class argument is not the class of the object argument, or if the slot argument does not appear among the set of effective slots associated with the class argument.

Methods

(CLOS:SLOT-BOUNDP-USING-CLASS (class STANDARD-CLASS) object (slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))
(CLOS:SLOT-BOUNDP-USING-CLASS (class CLOS:FUNCALLABLE-STANDARD-CLASS) object (slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))

These methods implement the full behavior of this generic function for slots with allocation :INSTANCE and :CLASS. If the supplied slot has an allocation other than :INSTANCE or :CLASS an ERROR is SIGNALed.

Overriding these methods is permitted, but may require overriding other methods in the standard implementation of the slot access protocol.

(CLOS:SLOT-BOUNDP-USING-CLASS (class BUILT-IN-CLASS) object slot)
This method SIGNALs an ERROR.

Remarks. In cases where the class metaobject class does not distinguish unbound slots, true should be returned.

29.1.10.3.7. Generic Function CLOS:SLOT-MAKUNBOUND-USING-CLASS
Syntax
(CLOS:SLOT-MAKUNBOUND-USING-CLASS class object slot)
Arguments
class
a class metaobject - the class of the object argument.
object
an object
slot
an effective slot definition metaobject.
Values
This generic function returns its object argument.
Purpose

This generic function implements the behavior of the SLOT-MAKUNBOUND function. It is called by SLOT-MAKUNBOUND with the class of object as its first argument and the pertinent effective slot definition metaobject as its third argument.

The generic function CLOS:SLOT-MAKUNBOUND-USING-CLASS restores a slot in an object to its unbound state. The interpretation of “restoring a slot to its unbound state” depends on the class metaobject class.

The results are undefined if the class argument is not the class of the object argument, or if the slot argument does not appear among the set of effective slots associated with the class argument.

Methods

(CLOS:SLOT-MAKUNBOUND-USING-CLASS (class STANDARD-CLASS) object (slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))
(CLOS:SLOT-MAKUNBOUND-USING-CLASS (class CLOS:FUNCALLABLE-STANDARD-CLASS) object (slot CLOS:STANDARD-EFFECTIVE-SLOT-DEFINITION))

These methods implement the full behavior of this generic function for slots with allocation :INSTANCE and :CLASS. If the supplied slot has an allocation other than :INSTANCE or :CLASS an ERROR is SIGNALed.

Overriding these methods is permitted, but may require overriding other methods in the standard implementation of the slot access protocol.

(CLOS:SLOT-MAKUNBOUND-USING-CLASS (class BUILT-IN-CLASS) object slot)
This method SIGNALs an ERROR.

29.1.11. Dependent Maintenance

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)))

29.1.11.1. Protocol

29.1.11.1.1. Generic Function CLOS:UPDATE-DEPENDENT
Syntax
(CLOS:UPDATE-DEPENDENT metaobject dependent &REST initargs)
Arguments
metaobject
a class or generic function metaobject - the metaobject being reinitialized or otherwise modified.
dependent
an object - the dependent being updated.
initargs
a list of the initialization arguments for the metaobject redefinition.
Values
The value returned by this generic function is unspecified.
Purpose

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.1.11, “Dependent Maintenance” for remarks about the use of this facility.

29.1.11.1.2. Generic Function CLOS:ADD-DEPENDENT
Syntax
(CLOS:ADD-DEPENDENT metaobject dependent)
Arguments
metaobject
a class or generic function metaobject
dependent
an object
Values
The value returned by this generic function is unspecified.
Purpose

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 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.1.11, “Dependent Maintenance” for remarks about the use of this facility.

29.1.11.1.3. Generic Function CLOS:REMOVE-DEPENDENT
Syntax
(CLOS:REMOVE-DEPENDENT metaobject dependent)
Arguments
metaobject
a class or generic function metaobject
dependent
an object
Values
The value returned by this generic function is unspecified.
Purpose

This 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.1.11, “Dependent Maintenance” for remarks about the use of this facility.

29.1.11.1.4. Generic Function CLOS:MAP-DEPENDENTS
Syntax
(CLOS:MAP-DEPENDENTS metaobject function)
Arguments
metaobject
a class or generic function metaobject.
function
a function which accepts one argument.
Values
The value returned by this generic function is unspecified.
Purpose
This generic function applies 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.1.11, “Dependent Maintenance” for remarks about the use of this facility.

29.1.12. Deviations from [AMOP]

This section lists the differences between the [AMOP] and the CLISP implementation thereof.

Not implemented in CLISP

Extensions specific to CLISP


These notes document CLISP version 2.41Last modified: 2006-10-13