# Meta-Object Protocol

Adapted from chapters 5 and 6 of &amop;

## Introduction

The &clos; specification (&ansi-cl; Chanpter 7) describes the standard Programmer Interface for the &cl; 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 &clos; Metaobject Protocol (MOP).

### 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-r; &y-r; &optional-amp; &v-r; &key-amp; &k-r;)

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

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-t; 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-r; &class;) &y-r; &optional-amp; &v-r; &key-amp; &k-r;)

This signature indicates that this primary method on the generic function `gf1` has two required parameters, named &x-r; and &y-r;. In addition, there is an optional parameter &v-r; and a keyword parameter &k-r;. This signature also indicates that the method's parameter specializers are the classes &class; and &t-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-t;)`.

### Package

The package exporting the &mop; symbols is unspecified.

&clisp-only;

The symbols specified by the &mop; are exported from the package &clos-pac; and &re-export;ed from the package &ext-pac;.

The package exporting the &mop; symbols is different in other implementations: In &sbcl; it is the package SB-MOP; in &openmcl; it is the package OPENMCL-MOP.

## Overview

### Metaobjects

For each kind of program element there is a corresponding basic metaobject class . These are the classes: &class;, &slot-definition-t;, &generic-function-t;, &method-t; and &method-combination-t;. 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&mo-prim; is an instance of a metaobject class.

metaobject class basic
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.

#### Classes

A class metaobject &mo-prim; class determines the structure and the default behavior of its instances. The following information is associated with &c-mo;s:

- 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 &c-mo;s.

- The slots defined directly in the class are available as a list of &dsdmo;s. The slots which are accessible in instances of the class are available as a list of &esdmo;s.

- The methods which use the class as a specializer, and the generic functions associated with those methods are available as lists of method and &gfmo;s respectively.

&doc-li;

See also

#### Slot Definitions

A slot definition metaobject &mo-prim; slot definition contains information about the definition of a slot. There are two kinds of &sdmo;s:

direct &mo-prim;slot definition direct &sdmo;

  Used to represent the direct definition of a slot in a class. This corresponds roughly to the slot specifiers found in &defclass; forms.

effective &mo-prim;slot definition effective &sdmo;

  Used to represent information, including inherited information, about a slot which is accessible in instances of a particular class.

Associated with each &c-mo; is a list of &dsdmo;s representing the slots defined directly in the class. Also associated with each &c-mo; is a list of &esdmo;s 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 &lex-env; is available as a function of no arguments which, when called, returns the result of evaluating the initialization form in its &lex-env;. This is called the initfunction of the slot.

- The slot filling initialization arguments are available as a list of symbols.

&doc-li;

Certain other information is only associated with &dsdmo;s. 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 &esdmo;s.

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

See also

#### Generic Functions

A generic function metaobject &mo-prim; generic function 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 &m-mo;s.

- The default class for this generic function's &m-mo;s is available as a &c-mo;.

- The &lalist; is available as a &list-t;.

- The method combination is available as a &mcmo;.

- The argument precedence order is available as a permutation of those symbols from the &lalist; which name the required arguments of the generic function.

- The declarations are available as a list of &declspec-glo;s.

  There is a slight misnomer in the naming of functions and options in this document: Where the term declaration is used, actually a &declspec-glo; is meant.

&doc-li;

See also

#### Methods

A method metaobject &mo-prim; method contains information about a specific &method-t;.

- The qualifiers are available as a &list-t; of of non-&nil; atoms.

- The &lalist; is available as a &list-t;.

- The specializers are available as a list of specializer metaobjects.

- The function is available as a &function-t;. 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 &gfmo; is available. A method can be associated with at most one generic function at a time.

&doc-li;

See also

#### Specializers

A specializer metaobject &mo-prim; specializer represents the specializers of a &method-t;. &c-mo;s are themselves specializer metaobjects. A special kind of specializer metaobject is used for &eql-t; specializers.

See also

#### Method Combinations

A method combination metaobject &mo-prim; method combination represents the information about the method combination being used by a generic function.

This document does not specify the structure of &mcmo;s.

See also

### Inheritance Structure of Metaobject Classes

Inheritance structure of metaobject classes

The inheritance structure of the specified metaobject classes is shown in . The class of every class shown is &standard-class; except for the classes &t-t; and &function-t;, which are instances of the class &built-in-class;, and the classes &generic-function-t; and &standard-generic-function-t;, which are instances of the class &funcallable-standard-class;.

Direct Superclass Relationships Among The Specified Metaobject Classes

Metaobject Class | Abstract | Subclassable | Direct Superclasses
--- | --- | --- | ---
&standard-object-t;&no-en; &yes-en; | (&t-t;)
&funcallable-standard-object-t;&no-en; &yes-en; | (&standard-object-t; &function-t;)
&metaobject-t;&yes-en; &no-en; | (&standard-object-t;)
&generic-function-t;&yes-en; &no-en; | (&metaobject-t; &funcallable-standard-object-t;)
&standard-generic-function-t;&no-en; &yes-en; | (&generic-function-t;)
&method-t;&yes-en; &no-en; | (&metaobject-t;)
&standard-method-t;&no-en; &yes-en; | (&method-t;)
&standard-accessor-method-t;&yes-en; &no-en; | (&standard-method-t;)
&standard-reader-method-t;&no-en; &yes-en; | (&standard-accessor-method-t;)
&standard-writer-method-t;&no-en; &yes-en; | (&standard-accessor-method-t;)
&method-combination-t;&yes-en; &no-en; | (&metaobject-t;)
&slot-definition-t;&yes-en; &no-en; | (&metaobject-t;)
&dsd-t;&yes-en; &no-en; | (&slot-definition-t;)
&esd-t;&yes-en; &no-en; | (&slot-definition-t;)
&standard-slotdef-t;&yes-en; &no-en; | (&slot-definition-t;)
&standard-dsd-t;&no-en; &yes-en; | (&standard-slotdef-t; &dsd-t;)
&standard-esd-t;&no-en; &yes-en; | (&standard-slotdef-t; &esd-t;)
&specializer-t;&yes-en; &no-en; | (&metaobject-t;)
&eql-specializer-t;&no-en; &no-en; | (&specializer-t;)
&class;&yes-en; &no-en; | (&specializer-t;)
&built-in-class;&no-en; &no-en; | (&class;)
&forward-referenced-class;&no-en; &no-en; | (&class;)
&standard-class;&no-en; &yes-en; | (&class;)
&funcallable-standard-class;&no-en; &yes-en; | (&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.

&clisp-only;

The class &method-t; is also subclassable: It is possible to create subclasses of &method-t; that do not inherit from &standard-method-t;.

Implementation dependent: only in &clisp; and some other implementations

The class &funcallable-standard-object-t;'s class precedence list contains &function-t; before &standard-object-t;, not after &standard-object-t;. 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-t;'s class precedence list contains &function-t; before &standard-object-t;.

The classes &standard-class;, &standard-dsd-t;, &standard-esd-t;, &standard-method-t;, &standard-reader-method-t;, &standard-writer-method-t; and &standard-generic-function-t; are called standard metaobject &mo-prim; standard 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;, &funcallable-standard-class; and &forward-referenced-class; are special-purpose &c-mo; classes. Built-in classes are instances of the class &built-in-class;. The class &funcallable-standard-class; provides a special kind of instances described in . When the definition of a class references another class which has not yet been defined, an instance of &forward-referenced-class; is used as a stand-in until the class is actually defined.

Implementation of class &forward-referenced-class; in &clisp;

The class &forward-referenced-class; is implemented in a way that fixes several flaws in the &amop; specification.

It is not a subclass of &class; and &specializer-t;, just a subclass of &metaobject-t;, 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, &forward-referenced-class; is formally a subclass of &class; and &specializer-t;, but the behaviour of &forward-referenced-class; instances is the same.

*FORWARD-REFERENCED-CLASS-MISDESIGN*

The &amop; says that the first argument of &ensure-class-UC; can be a &forward-referenced-class;. But from the description of &ensure-class;, it is clear that it can only be a class returned by &find-class;, and &ansi-cl; &find-class; cannot return a &forward-referenced-class;.

The &amop; says that &ensure-class-UC; creates a &forward-referenced-class; for not-yet-defined class symbols among the direct-superclasses list. But this leads to many &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, &forward-referenced-class; instances can occur, denoting classes that have not yet been defined. When or after such a class gets defined, the &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-t; 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-t;. In this way, any behavior associated with the class &standard-object-t; 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-t;.

The same is true for &funcallable-standard-class; and &funcallable-standard-object-t;.

The class &specializer-t; 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 &specializer-t; reflecting the property that classes by themselves can be used as method specializers. The class &eql-specializer-t; is used for &eql-t; specializers.

#### 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 &mo-prim; specified; those defined by an implementation but not mentioned in this document are called implementation-specific &mo-prim; implementation-specific; and those defined by a portable program are called portable &mo-prim; portable.

- A class &i-r; is interposed between two other classes &k1-r; and &k2-r; if and only if there is some path, following direct superclasses, from the class &k1-r; to the class &k2-r; which includes &i-r;.

  class interposed

- A method is specialized &me-prim;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 &me-prim;promoted if and only if the specializers of the method, &x1-r; ... &xn-r;, are defined in this specification as the classes &k1-r; ... &kn-r;, but in the implementation, one or more of the specializers x&sub-l;, is a superclass of the class given in the specification k&sub-l;.

- For a given generic function and set of arguments, a method &k2-r; extends &me-prim;extends a method &k1-r; if and only if:

  1. &k1-r; and &k2-r; are both associated with the given generic function

  2. &k1-r; and &k2-r; 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-r; is executed before &k1-r;,

  4. &k1-r; will be executed if and only if &call-next-method; is invoked from within the body of &k2-r; and

  5. &call-next-method; is invoked from within the body of &k2-r;, thereby causing &k1-r; to be executed.

- For a given generic function and set of arguments, a method &k2-r; overrides &me-prim;overrides a method &k1-r; 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-r;, thereby preventing &k1-r; from being executed.

##### 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-t; 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 &add-dependent;, &remove-dependent; and &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.

  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.

  &clisp-only;

  When a metaobject class is redefined, &clisp; issues a &warning-t; 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 ), and then &load; it only once per session.

&else-undefined;

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.

##### 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-r; that is a subclass of one or more specified classes &k1-r; ... &kn-r;, the following conditions are met:

- In the actual class precedence list of &k-r;, the classes &k1-r; ... &kn-r; 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-r; 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 &clu-pac; 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.

### Processing of the User Interface Macros

A list in which the first element is one of the symbols &defclass;, &defmethod;, &defgeneric;, &define-method-combination;, &gf-oper;, &gen-flet; or &gen-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-r; 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 &lex-env;.

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 .

#### Compile-file Processing of the User Interface Macros

It is a common practice for &cl; 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., &lalist; 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 &cl; 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.

#### Compile-file Processing of Specific User Interface Macros

&defclass;

  &clisp-only;

  &clisp; evaluates &defclass; forms also at &compile-time;.

&defmethod;

  &clisp-only;

  &clisp; does ¬-e; evaluate &defmethod; forms at &compile-time; except as necessary for signature checking.

&defgeneric;

  &clisp-only;

  &clisp; does ¬-e; evaluate &defgeneric; forms at &compile-time; except as necessary for signature checking.

### 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:

## Classes

### Macro &defclass;

The evaluation or execution of a &defclass; form results in a call to the &ensure-class; function. The arguments received by &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 &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 &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 &ensure-class;. Note that the order of the slot options has not affected the order of the properties in the &canonicalized-slot-spec;, 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-r; argument to &defclass; becomes the value of the first argument to &ensure-class;. This is the only positional argument accepted by &ensure-class;; all other arguments are keyword arguments.

- The &direct-superclasses-k; argument to &defclass; becomes the value of the &direct-superclasses-k; keyword argument to &ensure-class;.

- The &direct-slots-k; argument to &defclass; becomes the value of the &direct-slots-k; keyword argument to &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-spec;s is the value of the &direct-slots-k; 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-spec; is formed from the corresponding slot specification as follows:

  - The name of the slot is the value of the &name-k; property. This property appears in every &canonicalized-slot-spec;.

  - When the &initform-k; slot option is present in the slot specification, then both the &initform-k; and &initfunction-k; properties are present in the &canonicalized-slot-spec;. The value of the &initform-k; property is the initialization form. The value of the &initfunction-k; property is a function of zero arguments which, when called, returns the result of evaluating the initialization form in its proper &lex-env;.

  - If the &initform-k; slot option is not present in the slot specification, then either the &initfunction-k; property will not appear, or its value will be false. In such cases, the value of the &initform-k; property, or whether it appears, is unspecified.

  - The value of the &initargs-k; property is a list of the values of each &initarg-k; slot option. If there are no &initarg-k; slot options, then either the &initargs-k; property will not appear or its value will be the empty list.

  - The value of the &readers-k; property is a list of the values of each &reader-k; and &accessor-k; slot option. If there are no &reader-k; or &accessor-k; slot options, then either the &readers-k; property will not appear or its value will be the empty list.

  - The value of the &writers-k; property is a list of the values specified by each &writer-k; and &accessor-k; slot option. The value specified by a &writer-k; slot option is just the value of the slot option. The value specified by an &accessor-k; 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-k; or &accessor-k; slot options, then either the &writers-k; property will not appear or its value will be the empty list.

  - The value of the &documentation-k; property is the value of the &documentation-k; slot option. If there is no &documentation-k; slot option, then either the &documentation-k; 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-k; and &type-k;), 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-spec; provided these are not symbols accessible in the &clu-pac; 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-k; keyword argument to &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-initarg;s is the value of the &direct-default-initargs-k; keyword argument to &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 &lex-env;.

  &clisp-only;

  If a `:DEFAULT-INITARGS` class option is not present in the &defclass; form, &direct-default-initargs-k; &nil; is passed to &ensure-class;.

  &clisp-defclass-ensure-class-default;

- The &metaclass-k; class option, if it is present in the &defclass; form, becomes the value of the &metaclass-k; keyword argument to &ensure-class;.

  &clisp-only;

  If a &metaclass-k; class option is not present in the &defclass; form, &metaclass-k; &standard-class; is passed to &ensure-class;.

  &clisp-defclass-ensure-class-default;

- The &documentation-k; class option, if it is present in the &defclass; form, becomes the value of the &documentation-k; keyword argument to &ensure-class;.

  &clisp-only;

  If a &documentation-k; class option is not present in the &defclass; form, &direct-default-initargs-k; &nil; is passed to &ensure-class;.

  &clisp-defclass-ensure-class-default;

- 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 &err-sig; if any class option appears more than once in the &defclass; form.

  &clisp-only;

  The default initargs of the &metaclass-k; are added at the end of the list of arguments to pass to &ensure-class;.

  &clisp-defclass-ensure-class-default;

In the call to &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-spec;s is unspecified. The values of properties in &canonicalized-slot-spec;s do follow this ordering requirement. Other ordering relationships in the keyword arguments to &ensure-class; are unspecified.

The result of the call to &ensure-class; is returned as the result of evaluating or executing the &defclass; form.

### Inheritance Structure of &c-mo; Classes

Inheritance structure of &c-mo; classes

### Introspection: Readers for &c-mo;s

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 &c-mo;s are presented together in this section.

Each of the reader generic functions for &c-mo;s has the same syntax, accepting one required argument called &class-r;, which must be a &c-mo;; otherwise, an &err-sig;. An &error-t; is also &signal;ed if the &c-mo; has not been initialized.

&user-and-implementation-callable-result-immutable;

#### Generic Function &class-name;

`(&class-name; &class-r;)`

Returns the name of &class-r;. 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-k; initialization argument that was associated with the class during initialization or reinitialization. (Also see &setf-class-name;.)

#### Generic Function &class-direct-superclasses;

`(&class-direct-superclasses; &class-r;)`

Returns a list of the direct superclasses of &class-r;. The elements of this list are &c-mo;s. The empty list is returned if &class-r; has no direct superclasses. This is the defaulted value of the &direct-superclasses-k; initialization argument that was associated with the class during initialization or reinitialization.

&clisp-only;

For a class that has not yet been finalized, the returned list may contain &forward-referenced-class; instances as placeholder for classes that were not yet defined when finalization of the class was last attempted.

#### Generic Function &class-direct-slots;

`(&class-direct-slots; &class-r;)`

Returns a set of the direct slots of &class-r;. The elements of this set are &dsdmo;s. If the class has no direct slots, the empty set is returned. This is the defaulted value of the &direct-slots-k; initialization argument that was associated with the class during initialization and reinitialization.

#### Generic Function &class-direct-default-initargs;

`(&class-direct-default-initargs; &class-r;)`

Returns a list of the direct default initialization arguments for &class-r;. Each element of this list is a &canonicalized-default-initarg;. The empty list is returned if &class-r; has no direct default initialization arguments. This is the defaulted value of the &direct-default-initargs-k; initialization argument that was associated with the class during initialization or reinitialization.

#### Generic Function &cpl;

`(&cpl; &class-r;)`

Returns the class precedence list of &class-r;. The elements of this list are &c-mo;s.

During class finalization &finalize-inheritance; calls &compute-cpl; to compute the class precedence list of the class. That value is associated with the &c-mo; and is returned by &cpl;.

This generic function &sig-err; if &class-r; has not been finalized.

#### Generic Function &class-direct-subclasses;

`(&class-direct-subclasses; &class-r;)`

Returns a set of the direct subclasses of &class-r;. The elements of this set are &c-mo;s that all mention this class among their direct superclasses. The empty set is returned if &class-r; has no direct subclasses. This value is maintained by the generic functions &add-direct-subclass; and &remove-direct-subclass;.

&clisp-only;

The set of direct subclasses of a class is internally managed as a &weak-list;. Therefore the existence of the &class-direct-subclasses; function does not prevent otherwise unreferenced classes from being &gc;ed.

#### Generic Function &class-slots;

`(&class-slots; &class-r;)`

Returns a possibly empty set of the slots accessible in instances of &class-r;. The elements of this set are &esdmo;s.

During class finalization &finalize-inheritance; calls &compute-slots; to compute the slots of the class. That value is associated with the &c-mo; and is returned by &class-slots;.

This generic function &sig-err; if &class-r; has not been finalized.

#### Generic Function &class-default-initargs;

`(&class-default-initargs; &class-r;)`

Returns a list of the default initialization arguments for &class-r;. Each element of this list is a &canonicalized-default-initarg;. The empty list is returned if &class-r; has no default initialization arguments.

During finalization &finalize-inheritance; calls &compute-default-initargs; to compute the default initialization arguments for the class. That value is associated with the &c-mo; and is returned by &class-default-initargs;.

This generic function &sig-err; if &class-r; has not been finalized.

#### Generic Function &class-finalized-p;

`(&class-finalized-p; &class-r;)`

Returns true if &class-r; has been finalized. Returns false otherwise. Also returns false if the &class-r; has not been initialized.

#### Generic Function &class-prototype;

`(&class-prototype; &class-r;)`

Returns a prototype instance of &class-r;. 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 &sig-err; if &class-r; has not been finalized.

This allows non-&consing; access to slots with allocation &class-k;:

    (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 (&class-prototype; (&find-class; 'COUNTER)))`:

    (&make-instance; 'counted-object :name 'foo)
    #<COUNTED-OBJECT #x203028C9>
    (HOW-MANY (&class-prototype; (&find-class; 'counter)))
    1
    (&make-instance; 'counted-object :name 'bar)
    #<COUNTED-OBJECT #x20306CB1>
    (HOW-MANY (&class-prototype; (&find-class; 'counter)))
    2

#### Methods

The specified methods for the &c-mo; 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.

Generic Function | &standard-class;, &funcallable-standard-class; | &forward-referenced-class; | &built-in-class;
--- | --- | --- | ---
&class-name; |  |  |
&class-direct-superclasses; |  |  |
&class-direct-slots; |  |  |
&class-direct-default-initargs; |  |  |
&cpl; |  |  |
&class-direct-subclasses; |  |  |
&class-slots; |  |  |
&class-default-initargs; |  |  |
&class-finalized-p; |  |  |
&class-prototype; |  |  |

Class Reader Methods

1. This method returns the value which was associated with the &c-mo; during initialization or reinitialization.

2. This method returns the value associated with the &c-mo; by `&finalize-inheritance; (&standard-class;)` or `&finalize-inheritance; (&funcallable-standard-class;)`

3. This method &sig-err;.

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 , except that implementation-specific modifications are permitted as described in .

8. This method returns the name of the built-in class.

9. This method returns a value which is maintained by `&add-direct-subclass;(&class; &class;)` and `&remove-direct-subclass; (&class; &class;)`. This method can be overridden only if those methods are overridden as well.

10. &no-extra-spec;

### 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 &c-mo; 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.

class finalization

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 &c-mo;. Instead, finalization is done as a separate protocol, invoked by calling the generic function &finalize-inheritance;. The exact point at which &finalize-inheritance; is called depends on the class of the &c-mo;; 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 &compute-cpl;. The value returned from this call is associated with the &c-mo; and can be accessed by calling the &cpl; 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 &compute-slots;. The result of this call is a list of &esdmo;s. This value is associated with the &c-mo; and can be accessed by calling the &class-slots; generic function.

The behavior of &compute-slots; is itself layered, consisting of calls to &esd-class; and &compute-esd;.

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 &compute-default-initargs;. The value returned by this generic function is associated with the &c-mo; and can be accessed by calling &class-default-initargs;.

If the class was previously finalized, &finalize-inheritance; may call &make-instances-obsolete;. The circumstances under which this happens are described in the &ansi-cl; section .

Forward-referenced classes, which provide a temporary definition for a class which has been referenced but not yet defined, can never be finalized. An &err-sig; if &finalize-inheritance; is called on a forward-referenced class.

### Class Initialization

#### Initialization of &c-mo;s

A &c-mo; can be created by calling &make-instance;. The initialization arguments establish the definition of the class. A &c-mo; can be redefined by calling &reinitialize-instance;. Some classes of &c-mo; do not support redefinition; in these cases, &reinitialize-instance; &sig-err;.

Initialization of a &c-mo; must be done by calling &make-instance; and allowing it to call &initialize-instance;. Reinitialization of a &c-mo; must be done by calling &reinitialize-instance;. Portable programs must ¬-e;

- ... call &initialize-instance; directly to initialize a &c-mo;;

- ... call &shared-initialize; directly to initialize or reinitialize a &c-mo;;

- ... call &change-class; to change the class of any &c-mo; or to turn a non-class object into a &c-mo;.

Since metaobject classes may not be redefined, no behavior is specified for the result of calls to &update-instance-for-redefined-class; on &c-mo;s. Since the class of &c-mo;s may not be changed, no behavior is specified for the result of calls to &update-instance-for-different-class; on &c-mo;s.

During initialization or reinitialization, each initialization argument is checked for errors and then associated with the &c-mo;. The value can then be accessed by calling the appropriate accessor as shown in .

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 &c-mo; classes comes next. The section ends with a set of restrictions on portable methods affecting &c-mo; initialization and reinitialization.

In these descriptions, the phrase this argument defaults to &value-r; means that when that initialization argument is not supplied, initialization or reinitialization is performed as if &value-r; 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 &c-mo; classes. Portable programs are free to define default initialization arguments for portable subclasses of the class &class;.

&reinit-keep-value;

- The &direct-default-initargs-k; argument is a list of &canonicalized-default-initarg;s.

  An &err-sig; if this value is not a &proper-list-glo;, or if any element of the list is not a &canonicalized-default-initarg;.

  If the &c-mo; is being initialized, this argument defaults to the empty list.

- The &direct-slots-k; argument is a list of &canonicalized-slot-spec;s.

  An &err-sig; if this value is not a &proper-list-glo; or if any element of the list is not a &canonicalized-slot-spec;.

  After error checking, this value is converted to a list of &dsdmo;s before it is associated with the &c-mo;. Conversion of each &canonicalized-slot-spec; to a &dsdmo; is a two-step process. First, the generic function &dsd-class; is called with the &c-mo; and the &canonicalized-slot-spec; to determine the class of the new &dsdmo;; this permits both the &c-mo; and the &canonicalized-slot-spec; to control the resulting &dsdmo; class. Second, &make-instance; is applied to the direct &sdmo; class and the &canonicalized-slot-spec;. This conversion could be implemented as shown in the following code:

      (&defun; convert-to-direct-slot-definition (class canonicalized-slot)
        (&apply; #'&make-instance;
               (&apply; #'&dsd-class;
                      class canonicalized-slot)
               canonicalized-slot))

  If the &c-mo; is being initialized, this argument defaults to the empty list.

  Once the &dsdmo;s have been created, the specified reader and writer methods are created. The generic functions &reader-method-class; and &writer-method-class; are called to determine the classes of the &m-mo;s created.

- The &direct-superclasses-k; argument is a list of &c-mo;s. Classes which do not support multiple inheritance signal an error if the list contains more than one element.

  An &err-sig; if this value is not a &proper-list-glo; or if &validate-superclass; applied to &class-r; and any element of this list returns false.

  When the &c-mo; is being initialized, and this argument is either not supplied or is the empty list, this argument defaults as follows: if the class is an instance of &standard-class; or one of its subclasses the default value is a list of the class &standard-object-t;; if the class is an instance of &funcallable-standard-class; or one of its subclasses the default value is a list of the class &funcallable-standard-object-t;.

  &clisp-only;

  If the class is an instance of &structure-class; or one of its subclasses the default value is a list of the class &structure-object-t;

  After any defaulting of the value, the generic function &add-direct-subclass; is called once for each element of the list.

  When the &c-mo; is being reinitialized and this argument is supplied, the generic function &remove-direct-subclass; is called once for each &c-mo; in the previously stored value but not in the new value; the generic function &add-direct-subclass; is called once for each &c-mo; in the new value but not in the previously stored value.

&doc-k-li;

- The &name-k; argument is an object.

  If the class 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 &c-mo;. These values can then be accessed by calling the corresponding generic function. The correspondences are as follows:

Initialization arguments and accessors for &c-mo;s

Initialization Argument | Generic Function
--- | ---
&direct-default-initargs-k; | &class-direct-default-initargs;
&direct-slots-k; | &class-direct-slots;
&direct-superclasses-k; | &class-direct-superclasses;
&documentation-k; | &documentation;
&name-k; | &class-name;

Instances of the class &standard-class; support multiple inheritance and reinitialization. Instances of the class &funcallable-standard-class; support multiple inheritance and reinitialization. For &forward-referenced-class;es, all of the initialization arguments default to &nil;.

&clisp-only;

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 &err-sig; if &initialize-instance; or &reinitialize-instance; are called to initialize or reinitialize a derived instance of the class &built-in-class;.

##### 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 &c-mo; 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;: &init-method-restrictions;

&else-undefined;

##### Initialization of Anonymous Classes

&c-mo;s created with &make-instance; are usually anonymous ; that is, they have no &proper-name-glo;. An anonymous &c-mo; can be given a &proper-name-glo; using `(&setf; &find-class;)` and `(&setf; &class-name;)`.

class anonymous

When a &c-mo; 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 &c-mo;. The initialization arguments correspond roughly to the arguments accepted by the &defclass; macro, and more closely to the arguments accepted by the &ensure-class; function.

Some &c-mo; 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))))

#### Reinitialization of &c-mo;s

Some &c-mo; 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 &c-mo; was finalized before the call to &reinitialize-instance;, &finalize-inheritance; will be called again once all the initialization arguments have been processed and associated with the &c-mo;. In addition, once finalization is complete, any dependents of the &c-mo; will be updated by calling &update-dependent;.

### Customization

#### Generic Function &setf-class-name;

Syntax

  `(&setf-class-name; &nname-r; &class-r;)`

Arguments
  &class-mo-arg;
  &nname-r;

    any Lisp object.

Value

  The &nname-r; argument.

Purpose

  This function changes the name of &class-r; to &nname-r;. This value is usually a symbol, or &nil; if the class has no name.

  This function works by calling &reinitialize-instance; with &class-r; as its first argument, the symbol &name-k; as its second argument and &nname-r; as its third argument.

#### Generic Function &ensure-class;

Syntax

  `(&ensure-class; &name-r; &key-amp; &allow-other-keys-amp;)`

Arguments
  &name-r;

    a &symbol-t;.

  keyword arguments

    Some of the keyword arguments accepted by this function are actually processed by &ensure-class-UC;, others are processed during initialization of the &c-mo; (as described in ).

Value
&a-cmo;
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 &ensure-class-UC;. When &ensure-class; is called, it immediately calls &ensure-class-UC; and returns that result as its own.

  The first argument to &ensure-class-UC; is computed as follows:

  - If &name-r; names a class (&find-class; returns a class when called with &name-r;) use that class.

  - Otherwise use &nil;.

  The second argument is &name-r;. The remaining arguments are the complete set of keyword arguments received by the &ensure-class; function.

#### Generic Function &ensure-class-UC;

Syntax

  `(&ensure-class-UC; &class-r; &name-r; &key-amp; &direct-default-initargs-k; &direct-slots-k; &direct-superclasses-k; &name-k; &metaclass-k; &allow-other-keys-amp;)`

Arguments
  &class-r;

    a &c-mo; or &nil;.

  &name-r;

    a class name.

  &metaclass-k;

    a &c-mo; class or a &c-mo; 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 &err-sig;.

  &direct-superclasses-k;

    a list of which each element is a &c-mo; or a class name. An &err-sig; if this argument is not a &proper-list-glo;.

  additional keyword arguments

    See

Value
&a-cmo;
Purpose

  This generic function is called to define or modify the definition of a named class. It is called by the &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:

  - The &metaclass-k; argument is not included in the initialization arguments.

  - If the &direct-superclasses-k; argument was received by this generic function, it is converted into a list of &c-mo;s. This conversion does not affect the structure of the supplied &direct-superclasses-k; argument. For each element in the &direct-superclasses-k; argument:

    - If the element is a &c-mo;, that &c-mo; is used.

    - If the element names a class, that &c-mo; is used.

    - Otherwise an instance of the class &forward-referenced-class; is created and used. The &proper-name-glo; of the newly created forward referenced &c-mo; is set to the element.

      &clisp-only;

      A new &forward-referenced-class; instance is only created when one for the given class name does not yet exist; otherwise the existing one is reused. See .

  - All other keyword arguments are included directly in the initialization arguments.

  If the &class-r; argument is &nil;, a new &c-mo; is created by calling the &make-instance; generic function with the value of the &metaclass-k; argument as its first argument, and the previously computed initialization arguments. The &proper-name-glo; of the newly created &c-mo; is set to &name-r;. The newly created &c-mo; is returned.

  If the &class-r; argument is a &forward-referenced-class;, &change-class; is called to change its class to the value specified by the &metaclass-k; argument. The &c-mo; 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 &c-mo;s.)

  &clisp-only;

  The &class-r; argument cannot be a &forward-referenced-class;. See .

  If the class of the &class-r; argument is not the same as the class specified by the &metaclass-k; argument, an &err-sig;.

  Otherwise, the &c-mo; &class-r; is redefined by calling the &reinitialize-instance; generic function with &class-r; and the initialization arguments. The &class-r; argument is then returned.

Methods

`(&ensure-class-UC; (&class-r; &class;) &name-r; &key-amp; &metaclass-k; &direct-superclasses-k; &allow-other-keys-amp;)`

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

  &overridable;
`(&ensure-class-UC; (&class-r; &forward-referenced-class;) &name-r; &key-amp; &metaclass-k; &direct-superclasses-k; &allow-other-keys-amp;)`

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

  &clisp-only;

  This method does not exist. See . Use the method specialized on &null-t; instead.

`(&ensure-class-UC; (&class-r; &null-t;) &name-r; &key-amp; &metaclass-k; &direct-superclasses-k; &allow-other-keys-amp;)`

  This method implements the behavior of the generic function in the case where the &class-r; argument is &nil;.

#### Generic Function &finalize-inheritance;

Syntax

  `(&finalize-inheritance; &class-r;)`

Arguments
  &class-mo-arg;
&values-unspecified;
Purpose

  This generic function is called to finalize a &c-mo;. This is described in

  After &finalize-inheritance; returns, the &c-mo; is finalized and the result of calling &class-finalized-p; on the &c-mo; will be true.

Methods

`(&finalize-inheritance; (&class-r; &standard-class;))`
`(&finalize-inheritance; (&class-r; &funcallable-standard-class;))`
  &no-extra-specs;
`(&finalize-inheritance; (&class-r; &forward-referenced-class;))`

  This method &sig-err;.

#### Generic Function &make-instance;

Syntax

  `(&make-instance; &class-r; &rest-amp; &initargs-r;)`

Arguments
  &class-r;

    a &c-mo; or a class name.

  &initargs-r;

    a list of alternating initialization argument names and values.

Value

  A newly allocated and initialized instance of &class-r;.

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-r; &symbol-t;) &rest-amp; &initargs-r;)`

  This method simply invokes &make-instance; recursively on the arguments `(&find-class; &class-r;)` and &initargs-r;.

`(&make-instance; (&class-r; &standard-class;) &rest-amp; &initargs-r;)`
`(&make-instance; (&class-r; &funcallable-standard-class;) &rest-amp; &initargs-r;)`

  These methods implement the behavior of &make-instance; described in the &ansi-cl; section 7.1 Object Creation and Initialization.

#### Generic Function &allocate-instance;

Syntax

  `(&allocate-instance; &class-r; &rest-amp; &initargs-r;)`

Arguments
  &class-mo-arg;
  &initargs-r;

    alternating initialization argument names and values.

Value

  A newly allocated instance of &class-r;

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 &c-mo; class.

  Before allocating the new instance, &class-finalized-p; is called to see if &class-r; has been finalized. If it has not been finalized, &finalize-inheritance; is called before the new instance is allocated.

Methods

`(&allocate-instance; (&class-r; &standard-class;) &rest-amp; &initargs-r;`

  This method allocates storage in the instance for each slot with allocation &instance-k;. These slots are unbound. Slots with any other allocation are ignored by this method (no &err-sig;).

`(&allocate-instance; (&class-r; &funcallable-standard-class;) &rest-amp; &initargs-r;)`

  This method allocates storage in the instance for each slot with allocation &instance-k;. These slots are unbound. Slots with any other allocation are ignored by this method (no &err-sig;).

  The funcallable instance function of the instance is undefined - the results are undefined if the instance is applied to arguments before &set-funcallable-instance-function; has been used to set the funcallable instance function.

`(&allocate-instance; (&class-r; &built-in-class;) &rest-amp; &initargs-r;)`

  This method &sig-err;.

#### Generic Function &validate-superclass;

Syntax

  `(&validate-superclass; &class-r; &superclass-r;)`

Arguments
  &class-mo-arg;
  &superclass-r;
  &a-cmo;
Value

  &boolean-t;.

Purpose

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

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

Methods

`(&validate-superclass; (&class-r; &class;) (&superclass-r; &class;))`

  This method returns true in three situations:

  1. If the &superclass-r; argument is the class named &t-t;,

  2. if the class of the &class-r; argument is the same as the class of the &superclass-r; argument, or

  3. if the class of one of the arguments is &standard-class; and the class of the other is &funcallable-standard-class;.

  In all other cases, this method returns false. &overridable;
  &clisp-only;

  This method also returns true in a fourth situation:

  1. If the class of the &class-r; argument is a subclass of the class of the &superclass-r; argument.

Remarks

Defining a method on &validate-superclass; requires detailed knowledge of of the internal protocol followed by each of the two &c-mo; classes. A method on &validate-superclass; which returns true for two different &c-mo; classes declares that they are compatible.

#### Generic Function &compute-dsd-initargs;

&clisp-only;

Syntax

  `(&compute-dsd-initargs; &class-r; &rest-amp; &slot-spec-r;)`

Arguments
  &class-mo-arg;
  &slot-spec-r;

    a &canonicalized-slot-spec;.

Value

  A list of initialization arguments for a &dsdmo;.

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 &dsd-class; and then to &make-instance;.

  This generic function uses the supplied &canonicalized-slot-spec;. The value of &name-k; in the returned initargs is the same as the value of &name-k; in the supplied &slot-spec-r; argument.

Methods

`(&compute-dsd-initargs; (&class-r; &standard-class;) &rest-amp; &slot-spec-r;)`
`(&compute-dsd-initargs; (&class-r; &funcallable-standard-class;) &rest-amp; &slot-spec-r;)`

  This method returns &slot-spec-r; unmodified.

  This method can be overridden.

#### Generic Function &dsd-class;

Syntax

  `(&dsd-class; &class-r; &rest-amp; &initargs-r;)`

Arguments
  &class-mo-arg;
  &initargs-r;

    a set of initialization arguments and values.

Value

  A subclass of the class &dsd-t;.

Purpose

  When a class is initialized, each of the &canonicalized-slot-spec;s must be converted to a &dsdmo;. This generic function is called to determine the class of that &dsdmo;.

  The &initargs-r; argument is simply the &canonicalized-slot-spec; for the slot.

Methods

`(&dsd-class; (&class-r; &standard-class;) &rest-amp; &initargs-r;)`
`(&dsd-class; (&class-r; &funcallable-standard-class;) &rest-amp; &initargs-r;)`

  These methods return the class &standard-dsd-t;.

  &overridables;

#### Generic Function &compute-cpl;

Syntax

  `(&compute-cpl; &class-r;)`

Arguments
  &class-mo-arg;
Value

  A list of &c-mo;s.

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-r; and its superclasses once and only once. The first element of the list is &class-r; and the last element is the class named &t-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-r;. The results are undefined if the rules used to compute the class precedence list depend on any other factors.

  When a class is finalized, &finalize-inheritance; calls this generic function and associates the returned value with the &c-mo;. The value can then be accessed by calling &cpl;.

  &result-immutable;

Methods

`(&compute-cpl; (&class-r; &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 &sig-err; if &class-r; or any of its superclasses is a &forward-referenced-class;.

  &overridable;

#### Generic Function &compute-slots;

Syntax

  `(&compute-slots; &class-r;)`

Arguments
  &class-mo-arg;
Value

  A set of &esdmo;s.

Purpose

  This generic function computes a set of effective &sdmo;s for the class &class-r;. The result is a list of &esdmo;s: one for each slot that will be accessible in instances of &class-r;.

  This generic function proceeds in 3 steps:

  The first step collects the full set of direct slot definitions from the superclasses of &class-r;.

  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-t;. 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-r; appear before those coming from classes later in the class precedence list. For each slot name, the generic function &compute-esd; is called to compute an effective slot definition. The result of &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 .

  &result-immutable;

Methods

`(&compute-slots; (&class-r; &standard-class;))`
`(&compute-slots; (&class-r; &funcallable-standard-class;)}`

  These methods implement the specified behavior of the generic function.

  &overridables;
`(&compute-slots; `:AROUND` (&class-r; &standard-class;))`
`(&compute-slots; `:AROUND` (&class-r; &funcallable-standard-class;))`

  These methods implement the specified behavior of computing and storing slot locations. These methods cannot be overridden.

#### Generic Function &compute-esd;

Syntax

  `(&compute-esd; &class-r; &name-r; &dsds-r;)`

Arguments
  &class-mo-arg;
  &name-r;

    a slot name.

  &dsds-r;

    an ordered list of &dsdmo;s. The most specific &dsdmo; appears first in the list.

Value

  An &esdmo;.

Purpose

  This generic function determines the effective slot definition for a slot in a class. It is called by &compute-slots; once for each slot accessible in instances of &class-r;.

  This generic function uses the supplied list of &dsdmo;s 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 &esdmo; is determined by calling &esd-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 &esdmo;. See for details.

Methods

`(&compute-esd; (&class-r; &standard-class;) &name-r; &dsds-r;)`
`(&compute-esd; (&class-r; &funcallable-standard-class;) &name-r; &dsds-r;)`
  &implements-inheritance;

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

&clisp-only;

The initialization arguments that are passed to &esd-class; and &make-instance; are computed through a call to &compute-esd-initargs;. It is the &compute-esd-initargs; method that implements the inheritance rules.

#### Generic Function &compute-esd-initargs;

&clisp-only;

Syntax

  `(&compute-esd-initargs; &class-r; &dsds-r;)`

Arguments
  &class-mo-arg;
  &dsds-r;

    an ordered list of &dsdmo;s. The most specific &dsdmo; appears first in the list.

Value

  A list of initialization arguments for an &esdmo;.

Purpose

  This generic function determines the initialization arguments for the effective slot definition for a slot in a class. It is called by &compute-esd;. The resulting initialization arguments are passed to &esd-class; and then to &make-instance;.

  This generic function uses the supplied list of &dsdmo;s 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-k; in the returned initargs is the same as the name of the direct slot definitions supplied.

Methods

`(&compute-esd-initargs; (&class-r; &standard-class;) &dsds-r;)`
`(&compute-esd-initargs; (&class-r; &funcallable-standard-class;) &dsds-r;)`
  &implements-inheritance;

  This method can be extended.

#### Generic Function &esd-class;

Syntax

  `(&esd-class; &class-r; &rest-amp; &initargs-r;)`

Arguments
  &class-mo-arg;
  &initargs-r;

    set of initialization arguments and values.

Value

  A subclass of the class &esd-class;.

Purpose

  This generic function is called by &compute-esd; to determine the class of the resulting &esdmo;. The &initargs-r; argument is the set of initialization arguments and values that will be passed to &make-instance; when the &esdmo; is created.

Methods

`(&esd-class; (&class-r; &standard-class;) &rest-amp; &initargs-r;)`
`(&esd-class; (&class-r; &funcallable-standard-class;) &rest-amp; &initargs-r;)`

  These methods return the class &standard-esd-t;.

  &overridables;

#### Generic Function &compute-default-initargs;

Syntax

  `(&compute-default-initargs; &class-r;)`

Arguments
  &class-mo-arg;
Value

  A list of &canonicalized-default-initarg;s.

Purpose

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

  The result is a list of &canonicalized-default-initarg;s, 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-r;, 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, &finalize-inheritance; calls this generic function and associates the returned value with the &c-mo;. The value can then be accessed by calling &class-default-initargs;.

  &result-immutable;

Methods

`(&compute-default-initargs; (&class-r; &standard-class;))`
`(&compute-default-initargs; (&class-r; &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-r; or any of its superclasses is a &forward-referenced-class;.

  &overridables;

### Updating Dependencies

#### Generic Function &add-direct-subclass;

Syntax

  `(&add-direct-subclass; &superclass-r; &subclass-r;)`

Arguments
  &superclass-r;
  &a-cmo;
  &subclass-r;
  &a-cmo;
&values-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-r; to the set of direct subclasses of &superclass-r;.

  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 &remove-direct-subclass; is called once for each deleted direct superclass of the class.

Methods

`(&add-direct-subclass; (&superclass-r; &class;) (&subclass-r; &class;))`
  &no-extra-spec;

  &also-must-override;

  - `&remove-direct-subclass; (&class; &class;)`

  - `&class-direct-subclasses; (&class;)`

#### Generic Function &remove-direct-subclass;

Syntax

  `(&remove-direct-subclass; &superclass-r; &subclass-r;)`

Arguments
  &superclass-r;
  &a-cmo;
  &subclass-r;
  &a-cmo;
&values-unspecified;
Purpose

  This generic function is called to maintain a set of backpointers from a class to its direct subclasses. It removes &subclass-r; from the set of direct subclasses of &superclass-r;. No &err-sig; if &subclass-r; 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

`(&remove-direct-subclass; (&superclass-r; &class;) (&subclass-r; &class;))`
  &no-extra-spec;

  &also-must-override;

  - `&add-direct-subclass; (&class; &class;)`

  - `&class-direct-subclasses; (&class;)`

## Slot Definitions

### Inheritance Structure of &sdmo; Classes

Inheritance structure of &sdmo; classes

### Introspection: Readers for &sdmo;s

The reader generic functions which simply return information associated with &sdmo;s are presented together here in the format described in .

Each of the reader generic functions for &sdmo;s has the same syntax, accepting one required argument called &slot-r;, which must be a &sdmo;; otherwise, an &err-sig;. An &error-t; is also &signal;ed if the &sdmo; has not been initialized.

&user-and-implementation-callable-result-immutable;

#### Generic Functions

##### Generic Function &slotdef-name;

`(&slotdef-name; &slot-r;)`

Returns the name of &slot-r;. This value is a symbol that can be used as a variable name. This is the value of the &name-k; initialization argument that was associated with the &sdmo; during initialization.

&clisp-only;

The slot name does not need to be usable as a variable name. Slot names like &nil; or &t; are perfectly valid.

##### Generic Function &slotdef-allocation;

`(&slotdef-allocation; &slot-r;)`

Returns the allocation of &slot-r;. This is a symbol. This is the defaulted value of the &allocation-k; initialization argument that was associated with the &sdmo; during initialization.

##### Generic Function &slotdef-initform;

`(&slotdef-initform; &slot-r;)`

Returns the initialization form of &slot-r;. This can be any form. This is the defaulted value of the &initform-k; initialization argument that was associated with the &sdmo; during initialization. When &slot-r; has no initialization form, the value returned is unspecified (however, &slotdef-initfunction; is guaranteed to return &nil;).

##### Generic Function &slotdef-initfunction;

`(&slotdef-initfunction; &slot-r;)`

Returns the initialization function of &slot-r;. 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-k; initialization argument that was associated with the &sdmo; during initialization.

##### Generic Function &slotdef-type;

`(&slotdef-type; &slot-r;)`

Returns the type of &slot-r;. This is a &typespec-glo; name. This is the defaulted value of the &type-k; initialization argument that was associated with the &sdmo; during initialization.

##### Generic Function &slotdef-initargs;

`(&slotdef-initargs; &slot-r;)`

Returns the set of initialization argument keywords for &slot-r;. This is the defaulted value of the &initargs-k; initialization argument that was associated with the &sdmo; during initialization.

#### Methods

The specified methods for the &sdmo; readers

`(&slotdef-name; (&slotdef-r; &standard-slotdef-t;))`
`(&slotdef-allocation; (&slotdef-r; &standard-slotdef-t;))`
`(&slotdef-initform; (&slotdef-r; &standard-slotdef-t;))`
`(&slotdef-initfunction; (&slotdef-r; &standard-slotdef-t;))`
`(&slotdef-type; (&slotdef-r; &standard-slotdef-t;))`
`(&slotdef-initargs; (&slotdef-r; &standard-slotdef-t;))`
  &no-extra-specs;

#### Readers for &dsdmo;s

The following additional reader generic functions are defined for &dsdmo;s.

##### Generic Function &slotdef-readers;

`(&slotdef-readers; &dsd-r;)`

Returns a (possibly empty) set of readers of the &dsd-r;. This value is a list of function names. This is the defaulted value of the &readers-k; initialization argument that was associated with the direct &sdmo; during initialization.

##### Generic Function &slotdef-writers;

`(&slotdef-writers; &dsd-r;)`

Returns a (possibly empty) set of writers of the &dsd-r;. This value is a list of function names. This is the defaulted value of the &writers-k; initialization argument that was associated with the direct &sdmo; during initialization.

`(&slotdef-readers; (&dsd-r; &standard-dsd-t;))`
`(&slotdef-writers; (&dsd-r; &standard-dsd-t;))`
  &no-extra-specs;

#### Readers for &esdmo;s

The following reader generic function is defined for effective &sdmo;s.

##### Generic Function &slotdef-location;

`(&slotdef-location; &esd-r;)`

Returns the location of &esd-r;. The meaning and interpretation of this value is described in .

`(&slotdef-location; (&esd-r; &standard-esd-t;))`

  This method returns the value stored by `&compute-slots; `:AROUND` (&standard-class;)` and `&compute-slots; `:AROUND` (&funcallable-standard-class;)`.

### Initialization of &sdmo;s

A &sdmo; can be created by calling &make-instance;. The initialization arguments establish the definition of the slot definition. A &sdmo; cannot be redefined; calling &reinitialize-instance; &sig-err;.

Initialization of a &sdmo; must be done by calling &make-instance; and allowing it to call &initialize-instance;. Portable programs must ¬-e;...

- ... call &initialize-instance; directly to initialize a &sdmo;;

- ... call &shared-initialize; directly to initialize a &sdmo;;

- ... call &change-class; to change the class of any &sdmo; or to turn a non-slot-definition object into a &sdmo;.

Since metaobject classes may not be redefined, no behavior is specified for the result of calls to &update-instance-for-redefined-class; on &sdmo;s. Since the class of a &sdmo; cannot be changed, no behavior is specified for the result of calls to &update-instance-for-different-class; on &sdmo;s.

During initialization, each initialization argument is checked for errors and then associated with the &sdmo;. The value can then be accessed by calling the appropriate accessor as shown in .

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-r; means that when that initialization argument is not supplied, initialization is performed as if &value-r; 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 &sdmo; classes. Portable programs are free to define default initialization arguments for portable subclasses of the class &slotdef-t;.

- The &name-k; argument is a slot name. An &err-sig; if this argument is not a symbol which can be used as a variable name. An &err-sig; if this argument is not supplied.

  &clisp-only;

  The &name-k; argument does not need to be usable as a variable name. Slot names like &nil; or &t; are perfectly valid.

- The &initform-k; argument is a form. The &initform-k; argument defaults to &nil;. An &err-sig; if the &initform-k; argument is supplied, but the &initfunction-k; argument is not supplied.

- The &initfunction-k; argument is a function of zero arguments which, when called, evaluates the &initform-k; in the appropriate &lex-env;. The &initfunction-k; argument defaults to false. An &err-sig; if the &initfunction-k; argument is supplied, but the &initform-k; argument is not supplied.

- The &type-k; argument is a &typespec-glo; name. An &err-sig; otherwise. The &type-k; argument defaults to the symbol &t;.

- The &allocation-k; argument is a &symbol-t;. An &err-sig; otherwise. The &allocation-k; argument defaults to the symbol &instance-k;.

- The &initargs-k; argument is a &list-t; of &symbol-t;s. An &err-sig; if this argument is not a &proper-list-glo;, or if any element of this list is not a &symbol-t;. The &initargs-k; argument defaults to the empty list.

- The &readers-k; and &writers-k; arguments are &list-t;s of function names. An &err-sig; if they are not &proper-list-glo;s, or if any element is not a valid function name. They default to the empty list. An &err-sig; if either of these arguments is supplied and the metaobject is not a &dsd-t;.

&doc-k-li;

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

Initialization arguments and accessors for &sdmo;s

Initialization Argument | Generic Function
--- | ---
&name-k; | &slotdef-name;
&initform-k; | &slotdef-initform;
&initfunction-k; | &slotdef-initfunction;
&type-k; | &slotdef-type;
&allocation-k; | &slotdef-allocation;
&initargs-k; | &slotdef-initargs;
&readers-k; | &slotdef-readers;
&writers-k; | &slotdef-writers;
&documentation-k; | &documentation;

#### 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 &sdmo; 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 &slotdef-t;. 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;: &init-method-restrictions;

&else-undefined;

## Generic Functions

### Inheritance Structure of &gfmo; Classes

Inheritance structure of &gfmo; classes

### Introspection: Readers for &gfmo;s

The reader generic functions which simply return information associated with &gfmo;s are presented together here in the format described in .

Each of the reader generic functions for &gfmo;s has the same syntax, accepting one required argument called &gf-r;, which must be a &gfmo;; otherwise, an &err-sig;. An &error-t; is also &signal;ed if the &gfmo; has not been initialized.

&user-and-implementation-callable-result-immutable;

#### Generic Function &gf-name;

`(&gf-name; &gf-r;)`

Returns the name of the generic function, or &nil; if the generic function has no name. This is the defaulted value of the &name-k; initialization argument that was associated with the &gfmo; during initialization or reinitialization. (See also &setf-gf-name;.)

#### Generic Function &gf-methods;

`(&gf-methods; &gf-r;)`

Returns the set of methods currently connected to the generic function. This is a set of &m-mo;s. This value is maintained by the generic functions &add-method; and &remove-method;.

#### Generic Function &gf-lambda-list;

`(&gf-lambda-list; &gf-r;)`

Returns the &lalist; of the generic function. This is the defaulted value of the &lambda-list-k; initialization argument that was associated with the &gfmo; during initialization or reinitialization. An &err-sig; if the &lalist; has yet to be supplied.

#### Generic Function &gf-argument-precedence-order;

`(&gf-argument-precedence-order; &gf-r;)`

Returns the argument precedence order of the generic function. This value is a list of symbols, a permutation of the required parameters in the &lalist; of the generic function. This is the defaulted value of the &argument-precedence-order-k; initialization argument that was associated with the &gfmo; during initialization or reinitialization.

&clisp-only;

An &err-sig; if the &lalist; has not yet been supplied.

#### Generic Function &gf-declarations;

`(&gf-declarations; &gf-r;)`

Returns a possibly empty list of the declarations of the generic function. The elements of this list are &declspec-glo;s. This list is the defaulted value of the &declarations-k; initialization argument that was associated with the &gfmo; during initialization or reinitialization.

#### Generic Function &gf-method-class;

`(&gf-method-class; &gf-r;)`

Returns the default method class of the generic function. This class must be a subclass of the class &method-t;. This is the defaulted value of the &method-class-k; initialization argument that was associated with the &gfmo; during initialization or reinitialization.

#### Generic Function &gf-method-combination;

`(&gf-method-combination; &gf-r;)`

Returns the method combination of the generic function. This is a &mcmo;. This is the defaulted value of the &method-combination-k; initialization argument that was associated with the &gfmo; during initialization or reinitialization.

#### Methods

The specified methods for the &gfmo; reader generic functions

`(&gf-name; (&gf-r; &standard-generic-function-t;))`
`(&gf-lambda-list; (&gf-r; &standard-generic-function-t;))`
`(&gf-argument-precedence-order; (&gf-r; &standard-generic-function-t;))`
`(&gf-declarations; (&gf-r; &standard-generic-function-t;))`
`(&gf-method-class; (&gf-r; &standard-generic-function-t;))`
`(&gf-method-combination; (&gf-r; &standard-generic-function-t;))`
  &no-extra-specs;
`(&gf-methods; (&gf-r; &standard-generic-function-t;))`
  &no-extra-spec;

  The value returned by this method is maintained by `&add-method;(&standard-generic-function-t; &standard-method-t;)` and `&remove-method;(&standard-generic-function-t; &standard-method-t;)`.

### Initialization of Generic Functions

#### Macro &defgeneric;

The evaluation or execution of a &defgeneric; form results in a call to the &ensure-gf; function. The arguments received by &ensure-gf; 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-gf;.

- The &funcname-r; argument to &defgeneric; becomes the first argument to &ensure-gf;. This is the only positional argument accepted by &ensure-gf;; all other arguments are keyword arguments.

- The &lalist-r; argument to &defgeneric; becomes the value of the &lambda-list-k; keyword argument to &ensure-gf;.

- For each of the options &argument-precedence-order-k;, &documentation-k;, &gf-class-k; and &method-class-k;, 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-gf;.

  &clisp-only;

  If the option does not appear in the macro form, the keyword argument appears in the resulting call to &ensure-gf;, with a default value: the &lalist-r; for &argument-precedence-order-k;, &nil; for &documentation-k;, the class &standard-generic-function-t; for &gf-class-k;, the class &standard-method-t; for &method-class-k;. This is needed to make the generic function reflect the &defgeneric; form.

- For the option &declare-k;, the list of declarations becomes the value of the &declarations-k; keyword argument. If the &declare-k; option does not appear in the macro form, the &declarations-k; keyword argument does not appear in the call to &ensure-gf;.

  &clisp-only;

  If the &declare-k; option does not appear in the macro form, the &declarations-k; keyword argument appears in the resulting call to &ensure-gf;, with a default value of &nil;. This is needed to make the generic function reflect the &defgeneric; form.

- The handling of the &method-combination-k; option is not specified.

  &clisp-only;

  If the &method-combination-k; option does not appear in the macro form, the &method-combination-k; keyword argument still appears in the resulting call to &ensure-gf;, but in a position where it can be overridden by user-defined initargs and default initargs.

- &clisp-only;

  The &declare-k; keyword is recognized as equivalent to the &declarations-k; keyword, for compatibility with &ensure-gf; in &ansi-cl;. If both &declare-k; and &declarations-k; keyword arguments are specified, an &err-sig;.

  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 &err-sig; 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-gf;. This is needed to make the generic function reflect the &defgeneric; form.

- &clisp-only;

  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 &err-sig; if any option appears more than once in the &defgeneric; form.

The result of the call to &ensure-gf; is returned as the result of evaluating or executing the &defgeneric; form.

#### 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, &compute-discriminating-function;. Whenever a &gfmo; is initialized, reinitialized, or a method is added or removed, the discriminating function is recomputed. The new discriminating function is then stored with &set-funcallable-instance-function;.

Discriminating functions call &compute-applicable-methods-mop; and &compute-applicable-methods-UC; to compute the methods applicable to the generic functions arguments. Applicable methods are combined by &compute-effective-method; to produce an effective method &me-prim;effective. Provisions are made to allow memoization of the method applicability and effective methods computations. (See the description of &compute-discriminating-function; for details.)

The body of method definitions are processed by &make-method-lambda;. The result of this generic function is a &lambda-expr; which is processed by either &compile; or &compile-file; to produce a method function &me-prim;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, &make-method-lambda; must have created the method lambdas to expect additional arguments.

&clisp-only;

See .

See .

#### Initialization of &gfmo;s

A &gfmo; can be created by calling &make-instance;. The initialization arguments establish the definition of the generic function. A &gfmo; can be redefined by calling &reinitialize-instance;. Some classes of &gfmo; do not support redefinition; in these cases, &reinitialize-instance; &sig-err;.

Initialization of a &gfmo; must be done by calling &make-instance; and allowing it to call &initialize-instance;. Reinitialization of a &gfmo; must be done by calling &reinitialize-instance;. Portable programs must ¬-e;

- ... call &initialize-instance; directly to initialize a &gfmo;;

- ... call &shared-initialize; directly to initialize or reinitialize a &gfmo;;

- ... call &change-class; to change the class of any &gfmo; or to turn a non-generic-function object into a &gfmo;.

Since metaobject classes may not be redefined, no behavior is specified for the result of calls to &update-instance-for-redefined-class; on &gfmo;s. Since the class of a &gfmo; may not be changed, no behavior is specified for the results of calls to &update-instance-for-different-class; on &gfmo;s.

During initialization or reinitialization, each initialization argument is checked for errors and then associated with the &gfmo;. The value can then be accessed by calling the appropriate accessor as shown in .

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 &gfmo; initialization and reinitialization.

In these descriptions, the phrase this argument defaults to &value-r; means that when that initialization argument is not supplied, initialization or reinitialization is performed as if &value-r; 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 &gfmo; classes. Portable programs are free to define default initialization arguments for portable subclasses of the class &generic-function-t;.

&reinit-keep-value;

- The &argument-precedence-order-k; argument is a list of symbols.

  An &err-sig; if this argument appears but the &lambda-list-k; argument does not appear. An &err-sig; if this value is not a &proper-list-glo; or if this value is not a permutation of the symbols from the required arguments part of the &lambda-list-k; initialization argument.

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

- The &declarations-k; argument is a list of &declspec-glo;s.

  An &err-sig; if this value is not a &proper-list-glo; or if each of its elements is not a legal &declspec-glo;.

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

&doc-k-li;

- The &lambda-list-k; argument is a &lalist;.

  An &err-sig; if this value is not a proper generic function &lalist;.

  When the generic function is being initialized, and this argument is not supplied, the generic function's &lalist; is not initialized. The &lalist; 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-k; argument is a &mcmo;.

- The &method-class-k; argument is a &c-mo;.

  An &err-sig; if this value is not a subclass of the class &method-t;.

  When the generic function is being initialized, and this argument is not supplied, it defaults to the class &standard-method-t;.

- The &name-k; 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 &gfmo;. These values can then be accessed by calling the corresponding generic function. The correspondences are as follows:

Initialization arguments and accessors for &gfmo;s

Initialization Argument | Generic Function
--- | ---
&argument-precedence-order-k; | &gf-argument-precedence-order;
&declarations-k; | &gf-declarations;
&documentation-k; | &documentation;
&lambda-list-k; | &gf-lambda-list;
&method-combination-k; | &gf-method-combination;
&method-class-k; | &gf-method-class;
&name-k; | &gf-name;

##### 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 &gfmo; 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-t;. 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;: &init-method-restrictions;

&else-undefined;

### Customization

#### Generic Function &setf-gf-name;

Syntax

  `(&setf-gf-name; &nname-r; &gf-r;)`

Arguments
  &gf-mo-arg;
  &nname-r;

    a &funname; or &nil;.

Value

  The &nname-r; argument.

Purpose

  This function changes the name of &gf-r; to &nname-r;. This value is usually a &funname; or &nil;, if the generic function is to have no name.

  This function works by calling &reinitialize-instance; with &gf-r; as its first argument, the symbol &name-k; as its second argument and &nname-r; as its third argument.

#### Generic Function &ensure-gf;

Syntax

  `(&ensure-gf; &funcname-r; &key-amp; &allow-other-keys-amp;)`

Arguments
  &funcname-r;

    a &funname;

  keyword arguments

    Some of the keyword arguments accepted by this function are actually processed by &ensure-gf-UC;, others are processed during initialization of the &gfmo; (as described in ).

Value

  A &gfmo;.

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 &ensure-gf-UC;. When &ensure-gf; is called, it immediately calls &ensure-gf-UC; and returns that result as its own.

  The first argument to &ensure-gf-UC; is computed as follows:

  - If &funcname-r; names a non-generic function, a macro, or a special form, an &err-sig;.

  - If &funcname-r; names a generic function, that &gfmo; is used.

  - Otherwise, &nil; is used.

  The second argument is &funcname-r;. The remaining arguments are the complete set of keyword arguments received by &ensure-gf;.

#### Generic Function &ensure-gf-UC;

Syntax

  `(&ensure-gf-UC; &gf-r; &funcname-r; &key-amp; &argument-precedence-order-k; &declarations-k; &documentation-k; &gf-class-k; &lambda-list-k; &method-class-k; &method-combination-k; &name-k; &allow-other-keys-amp;)`

Arguments
  &gf-r;

    a &gfmo; or &nil;.

  &funcname-r;

    a &funname;

  &gf-class-k;

    a &c-mo; or a class name. If it is not supplied, it defaults to the class named &standard-generic-function-t;. 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 &err-sig;.

  additional keyword arguments

    see .

    &clisp-only;

    The &declare-k; keyword is recognized as equivalent to the &declarations-k; keyword, for compatibility with &ensure-gf; in &ansi-cl;.

Value

  A &gfmo;.

Purpose

  The generic function &ensure-gf-UC; is called to define or modify the definition of a globally named generic function. It is called by the &ensure-gf; 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 &gf-class-k; argument is not included in the initialization arguments.

  - If the &method-class-k; argument was received by this generic function, it is converted into a &c-mo;. This is done by looking up the class name with &find-class;. If there is no such class, an &err-sig;.

  - All other keyword arguments are included directly in the initialization arguments.

  If the &gf-r; argument is &nil;, an instance of the class specified by the &gf-class-k; argument is created by calling &make-instance; with the previously computed initialization arguments. The function name &funcname-r; is set to name the generic function. The newly created &gfmo; is returned.

  If the class of the &gf-r; argument is not the same as the class specified by the &gf-class-k; argument, an &err-sig;.

  &clisp-only;

  The description of &ensure-gf; in &ansi-cl; specifies that in this case, &change-class; is called if the class of the &gf-r; argument and the class specified by the &gf-class-k; argument are compatible. Given the description of &ensure-gf;, this also applies to the &ensure-gf-UC; 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 &gf-r; is redefined by calling the &reinitialize-instance; generic function with &gf-r; and the initialization arguments. The &gf-r; argument is then returned.

Methods

`(&ensure-gf-UC; (&gf-r; &generic-function-t;) &funcname-r; &key-amp; &gf-class-k; &allow-other-keys-amp;)`

  This method implements the behavior of the generic function in the case where &funcname-r; names an existing generic function.

  &overridable;
`(&ensure-gf-UC; (&gf-r; &null-t;) &funcname-r; &key-amp; &gf-class-k; &allow-other-keys-amp;)`

  This method implements the behavior of the generic function in the case where &funcname-r; names no function, generic function, macro or special form.

#### Generic Function &add-method;

Syntax

  `(&add-method; &gf-r; &method-r;)`

Arguments
  &gf-mo-arg; &method-mo-arg;
Value

  The &gf-r; argument.

Purpose

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

  An &err-sig; if the &lalist; of the method is not congruent with the &lalist; of the generic function.

  An &err-sig; 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-r; to the set returned by &gf-methods; and arrange for &method-gf; to return &gf-r;;

  2. call &add-direct-method; for each of the method's specializers;

  3. call &compute-discriminating-function; and install its result with &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; (&gf-r; &standard-generic-function-t;) (&method-r; &standard-method-t;))`
  &no-extra-spec;
`(&add-method; (&gf-r; &standard-generic-function-t;) (&method-r; &method-t;))`

  This method is specified by &ansi-cl;.

#### Generic Function &remove-method;

Syntax

  `(&remove-method; &gf-r; &method-r;)`

Arguments
  &gf-mo-arg; &method-mo-arg;
Value

  The &gf-r; argument.

Purpose

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

  No &err-sig; 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-r; from the set returned by &gf-methods; and arrange for &method-gf; to return &nil;;

  2. call &remove-direct-method; for each of the method's specializers;

  3. call &compute-discriminating-function; and install its result with &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; (&gf-r; &standard-generic-function-t;) (&method-r; &standard-method-t;))`
  &no-extra-spec;
`(&remove-method; (&gf-r; &standard-generic-function-t;) (&method-r; &method-t;))`

  This method is specified by &ansi-cl;.

#### Generic Function &compute-applicable-methods-mop;

Syntax

  `(&compute-applicable-methods-mop; &gf-r; &args-r;)`

Arguments
  &gf-mo-arg;
  &args-r;

    a list of objects.

Value

  A possibly empty list of &m-mo;s.

Purpose

  This generic function determines the method applicability of a generic function given a list of required arguments. The returned list of &m-mo;s 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.

  &cam-cdf;

  The &args-r; argument is permitted to contain more elements than the generic function accepts required arguments; in these cases the extra arguments will be ignored. An &err-sig; if &args-r; contains fewer elements than the generic function accepts required arguments.

  &result-immutable;

Methods

`(&compute-applicable-methods-mop; (&gf-r; &standard-generic-function-t;) &args-r;)`

  This method &sig-err; if any method of the generic function has a specializer which is neither a &c-mo; nor an &eql-t; 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 &compute-applicable-methods-UC;, doing so may require also overriding `&compute-applicable-methods-UC; (&standard-generic-function-t; &t-t;)`.

Remarks

See also the &ansi-cl; function &compute-applicable-methods;.

#### Generic Function &compute-applicable-methods-UC;

Syntax

  `(&compute-applicable-methods-UC; &gf-r; &classes-r;)`

Arguments
  &gf-mo-arg;
  &classes-r;

    a list of &c-mo;s.

Values

  1. A possibly empty list of &m-mo;s.

  2. &boolean-t;

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 &pri-val; and true as its second value. The returned list of &m-mo;s 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 &pri-val; and false as its second value.

  &cam-cdf;

  The following consistency relationship between &compute-applicable-methods-UC; and &compute-applicable-methods-mop; must be maintained: for any given generic function and set of arguments, if &compute-applicable-methods-UC; returns a second value of true, the &pri-val; must be equal to the value that would be returned by a corresponding call to &compute-applicable-methods-mop;. The results are undefined if a portable method on either of these generic functions causes this consistency to be violated.

  &result-immutable;

Methods

`(&compute-applicable-methods-UC; (&gf-r; &standard-generic-function-t;) &classes-r;)`

  If any method of the generic function has a specializer which is neither a &c-mo; nor an &eql-t; specializer metaobject, this method &sig-err;.

  In cases where the generic function has no methods with &eql-t; specializers, or has no methods with &eql-t; 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 &pri-val; and false as its second value.

  This method can be overridden. Because of the consistency requirements between this generic function and &compute-applicable-methods-mop;, doing so may require also overriding `&compute-applicable-methods-mop; (&standard-generic-function-t; &t-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 &compute-applicable-methods-mop;. 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 &compute-discriminating-function; which implement their own memoization scheme.

#### Generic Function &compute-effective-method;

Syntax

  `(&compute-effective-method; &gf-r; &mc-r; &methods-r;)`

Arguments
  &gf-mo-arg;
  &mc-r;

    a &mcmo;.

  &methods-r;

    a list of &m-mo;s.

Values

  1. An effective method

  2. A list of effective method options

Purpose

  This generic function is called to determine the effective method from a sorted list of &m-mo;s.

  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 &make-method-lambda; for more details about method functions.)

  An effective method option has the same interpretation and syntax as either the &arguments-k; or the &gf-k; 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

`(&compute-effective-method; (&gf-r; &standard-generic-function-t;) &mc-r; &methods-r;)`

  This method computes the effective method according to the rules of the method combination type implemented by &mc-r;.

  &overridable;

&clisp-only;

The second return value may contain only one &arguments-k; option and only one &gf-k; option. When overriding a &compute-effective-method; method, before adding an &arguments-k; or &gf-k; option, you therefore need to check whether it this option is already present.

#### Function &compute-effective-method-as-function;

&clisp-only;

Syntax

  `(&compute-effective-method-as-function; &gf-r; &methods-r; &args-r;)`

Arguments
  &gf-mo-arg;
  &methods-r;

    a list of &m-mo;s.

  &args-r;

    a list of arguments.

Value

  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 &m-mo;s, and convert it to a function. The &args-r; are a set of arguments to which the methods are applicable, and are used solely for error message purposes.

  This function calls &compute-effective-method; using the &gf-r;'s method combination, wraps local macro definitions for &call-method; and &make-method; around it, handles the &arguments-k; and &gf-k; options, and compiles the resulting form to a function.

#### Generic Function &make-method-lambda;

Syntax

  `(&make-method-lambda; &gf-r; &method-r; &laexpr-r; &env-r;)`

Arguments
  &gf-mo-arg;
  &method-r;

    a (possibly uninitialized) &m-mo;.

  &laexpr-r;

    a &lambda-expr;.

  &env-r;

    the same as the &environment-amp; argument to macro expansion functions.

Values

  1. A &lambda-expr;

  2. A list of initialization arguments and values

Purpose

  This generic function is called to produce a &lambda-expr; 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 &m-mo; may be uninitialized.

  Either the function &compile;, the special form &function; or the function &coerce; must be used to convert the &lambda-expr; 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 &make-method-lambda; and &compute-effective-method; must be consistent in the following way: each use of &call-method; returned by the method on &compute-effective-method; must have the same number of arguments, and the method lambda returned by the method on &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 &m-mo; is created with &make-instance;, the method function must be the value of the &function-k; 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

`(&make-method-lambda; (&gf-r; &standard-generic-function-t;) (&method-r; &standard-method-t;) &laexpr-r; &env-r;)`

  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.

  &overridable;

This example shows how to define a kind of method which, from within the body of the method, has access to the actual &m-mo; 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-amp; 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)))

&clisp-only;

The generic function &make-method-lambda; is not implemented

Its specification is misdesigned: it mixes &compile-time; and &exec-time; behaviour. The essential problem is: where could the generic-function argument come from?

- If a &defmethod; form occurs in a source file, is &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 &make-method-lambda; then be called again or not? If no, then &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.

#### Generic Function &compute-discriminating-function;

Syntax

  `(&compute-discriminating-function; &gf-r;)`

Arguments
  &gf-mo-arg;
Value

  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 &compute-applicable-methods-UC;. If &compute-applicable-methods-UC; returns a second value of false, the discriminating function then calls &compute-applicable-methods-mop;.

  When &compute-applicable-methods-UC; returns a second value of true, the discriminating function is permitted to memoize the &pri-val; as follows. The discriminating function may reuse the list of applicable methods without calling &compute-applicable-methods-UC; 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 &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 &make-method-lambda; for more information about how method functions are called.)

  The generic function &compute-discriminating-function; is called, and its result installed, by &add-method;, &remove-method;, &initialize-instance; and &reinitialize-instance;.

Methods

`(&compute-discriminating-function; (&gf-r; &standard-generic-function-t;))`
  &no-extra-spec; &overridable;

&clisp-only;

Overriding methods can make use of the function &compute-effective-method-as-function;. It is more convenient to call &compute-effective-method-as-function; than &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 &compute-effective-method;.

## Methods

### Inheritance Structure of &m-mo; Classes

Inheritance structure of &m-mo; classes

### Introspection: Readers for &m-mo;s

The reader generic functions which simply return information associated with &m-mo;s are presented together here in the format described in .

Each of these reader generic functions have the same syntax, accepting one required argument called &method-r;, which must be a &m-mo;; otherwise, an &err-sig;. An &error-t; is also &signal;ed if the &m-mo; has not been initialized.

&user-and-implementation-callable-result-immutable;

#### Generic Function &method-specializers;

`(&method-specializers; &method-r;)`

Returns a list of the specializers of &method-r;. This value is a list of specializer metaobjects. This is the value of the &specializers-k; initialization argument that was associated with the method during initialization.

#### Generic Function &method-qualifiers;

`(&method-qualifiers; &method-r;)`

Returns a (possibly empty) list of the qualifiers of &method-r;. This value is a list of non-&nil; atoms. This is the defaulted value of the &qualifiers-k; initialization argument that was associated with the method during initialization.

#### Generic Function &method-lambda-list;

`(&method-lambda-list; &method-r;)`

Returns the (unspecialized) &lalist; of &method-r;. This value is a &cl; &lalist;. This is the value of the &lambda-list-k; initialization argument that was associated with the method during initialization.

#### Generic Function &method-gf;

`(&method-gf; &method-r;)`

Returns the generic function that &method-r; is currently connected to, or &nil; if it is not currently connected to any generic function. This value is either a &gfmo; 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;.

#### Generic Function &method-function;

`(&method-function; &method-r;)`

Returns the method function of &method-r;. This is the value of the &function-k; initialization argument that was associated with the method during initialization.

#### Methods

The specified methods for the &m-mo; readers

`(&method-specializers; (&method-r; &standard-method-t;))`
`(&method-qualifiers; (&method-r; &standard-method-t;))`
`(&method-lambda-list; (&method-r; &standard-method-t;))`
`(&method-function; (&method-r; &standard-method-t;))`
  &no-extra-specs;
`(&method-gf; (&method-r; &standard-method-t;))`
  &no-extra-spec;

  The value returned by this method is maintained by `&add-method;(&standard-generic-function-t; &standard-method-t;)` and `&remove-method;(&standard-generic-function-t; &standard-method-t;)`.

### Initialization of Methods

#### 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-gf;. 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 &m-mo; by calling &make-instance;. The class of the new &m-mo; is determined by calling &gf-method-class; on the result of the call to &ensure-gf; from the first step.

The initialization arguments received by the call to &make-instance; are as follows:

- The value of the &qualifiers-k; 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-k; initialization argument is the unspecialized &lalist; from the &defmethod; form.

- The value of the &specializers-k; initialization argument is a list of the specializers for the method. For specializers which are classes, the specializer is the &c-mo; itself. In the case of &eql-t; specializers, it will be an &eql-specializer-t; metaobject obtained by calling &intern-eql-specializer; on the result of evaluating the &eql-t; specializer form in the &lex-env; of the &defmethod; form.

- The value of the &function-k; initialization argument is the method function.

- The value of the &declarations-k; initialization argument is a list of the &declspec-glo;s 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.

  &clisp-only;

  No &declarations-k; initialization argument is provided, because method initialization does not support a &declarations-k; argument, and because the method function is already completely provided through the &function-k; initialization argument.

- The value of the &documentation-k; 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 &clu-pac; 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 &gfmo;.

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 &make-method-lambda; as described in . The initargs appearing after &function-k; are assumed to be additional initargs returned from the call to &make-method-lambda;.

    (defmethod move :before ((p position) (l (eql 0))
                             &optional-amp; (visiblyp t)
                             &key-amp; 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-amp; (visiblyp t)
                                          &key-amp; 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.

##### 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.

The body of methods can also appear in the &method-k; 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, &env-r; 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-amp; (visiblyp t) &key-amp; color)
           (set-to-origin p)
           (when visiblyp (show-move p 0 color)))
        &env-r;))

The first step occurs during macro-expansion of the macro form. In this step, the method &lalist;, declarations and body are converted to a &lambda-expr; called a method lambda &me-prim;function. 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-gf; with a first argument of the generic function name specified in the macro form. The &lambda-list-k; keyword argument is not passed in this call.

Given the generic function, production of the method lambda proceeds by calling &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 &class-prototype; on the result of calling &gf-method-class; on the generic function. The third argument is a &lambda-expr; formed from the method &lalist;, declarations and body. The fourth argument is the macro-expansion environment of the macro form; this is the value of the &environment-amp; argument to the &defmethod; macro.

The generic function &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.

&clisp-only;

See .

##### Initialization of Generic Function and &m-mo;s

An example of creating a generic function and a &m-mo;, 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-amp; visiblyp &key-amp;)))
           (method-class (generic-function-method-class gf)))
      (multiple-value-bind (lambda initargs)
           (make-method-lambda
             gf
             (class-prototype method-class)
             '(lambda (p l &optional-amp; (visiblyp t) &key-amp; 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-amp; (visiblyp t)
                                              &key-amp; color)
                           initargs))))

##### 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.

#### Initialization of &m-mo;s

A &m-mo; can be created by calling &make-instance;. The initialization arguments establish the definition of the method. A &m-mo; cannot be redefined; calling &reinitialize-instance; &sig-err;.

Initialization of a &m-mo; must be done by calling &make-instance; and allowing it to call &initialize-instance;. Portable programs must ¬-e;

- ... call &initialize-instance; directly to initialize a &m-mo;;

- ... call &shared-initialize; directly to initialize a &m-mo;;

- ... call &change-class; to change the class of any &m-mo; or to turn a non-method object into a &m-mo;.

Since metaobject classes may not be redefined, no behavior is specified for the result of calls to &update-instance-for-redefined-class; on &m-mo;s. Since the class of a &m-mo; cannot be changed, no behavior is specified for the result of calls to &update-instance-for-different-class; on &m-mo;s.

During initialization, each initialization argument is checked for errors and then associated with the &m-mo;. The value can then be accessed by calling the appropriate accessor as shown in .

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 &m-mo; initialization.

In these descriptions, the phrase this argument defaults to &value-r; means that when that initialization argument is not supplied, initialization is performed as if &value-r; 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 &m-mo; classes. Portable programs are free to define default initialization arguments for portable subclasses of the class &method-t;.

- The &qualifiers-k; argument is a list of method qualifiers. An &err-sig; if this value is not a &proper-list-glo;, or if any element of the list is not a non-null atom. This argument defaults to the empty list.

- The &lambda-list-k; argument is the unspecialized &lalist; of the method. An &err-sig; if this value is not a proper &lalist;. If this value is not supplied, an &err-sig;.

- The &specializers-k; argument is a list of the specializer metaobjects for the method. An &err-sig; if this value is not a &proper-list-glo;, or if the length of the list differs from the number of required arguments in the &lambda-list-k; argument, or if any element of the list is not a specializer metaobject. If this value is not supplied, an &err-sig;.

- The &function-k; argument is a method function. It must be compatible with the methods on &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 &compute-effective-method; and &make-method-lambda; for more information.) An &err-sig; if this argument is not supplied.

- When the method being initialized is an instance of a subclass of &standard-accessor-method-t;, the &slotdef-k; initialization argument must be provided. Its value is the direct &sdmo; which defines this accessor method. An &err-sig; if the value is not an instance of a subclass of &dsd-t;.

- The &documentation-k; argument is a string or &nil;. An &err-sig; 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 &m-mo;. These values can then be accessed by calling the corresponding generic function. The correspondences are as follows:

Initialization arguments and accessors for &m-mo;s

Initialization Argument | Generic Function
--- | ---
&qualifiers-k; | &method-qualifiers;
&lambda-list-k; | &method-lambda-list;
&specializers-k; | &method-specializers;
&function-k; | &method-function;
&slotdef-k; | &accessor-method-slotdef;
&documentation-k; | &documentation;

##### 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 &m-mo; 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-t;. 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;: &init-method-restrictions;

&else-undefined;

### Customization

#### Function &extract-lambda-list;

Syntax

  `(&extract-lambda-list; &spec-lalist-r;)`

Arguments
  &spec-lalist-r;

    a &spelalist; as accepted by &defmethod;.

Value

  An unspecialized &lalist;.

Purpose

  This function takes a &spelalist; and returns the &lalist; with the specializers removed. This is a non-destructive operation. Whether the result shares any structure with the argument is unspecified.

  If the &spec-lalist-r; argument does not have legal syntax, an &err-sig;. This syntax checking does not check the syntax of the actual specializer names, only the syntax of the &lalist; and where the specializers appear.

    (&extract-lambda-list; '((p position)))
    (P)
    (&extract-lambda-list; '((p position) x y))
    (P X Y)
    (&extract-lambda-list; '(a (b (eql x)) c &rest-amp; i))
    (A B C &optional-amp; I)

#### Function &extract-specializer-names;

Syntax

  `(&extract-specializer-names; &spec-lalist-r;)`

Arguments
  &spec-lalist-r;

    a &spelalist; as accepted by &defmethod;.

Value

  A list of specializer names.

Purpose

  This function takes a &spelalist; and returns its specializer names. This is a non-destructive operation. Whether the result shares structure with the argument is unspecified.

  &result-immutable;

  The result of this function will be a list with a number of elements equal to the number of required arguments in &spec-lalist-r;. Specializers are defaulted to the symbol &t-t;.

  If the &spec-lalist-r; argument does not have legal syntax, an &err-sig;. This syntax checking does not check the syntax of the actual specializer names, only the syntax of the &lalist; and where the specializers appear.

    (&extract-specializer-names; '((p position)))
    (POSITION)
    (&extract-specializer-names; '((p position) x y))
    (POSITION T T)
    (&extract-specializer-names; '(a (b (eql x)) c &rest-amp; i))
    (T (EQL X) T)

## Accessor Methods

### Introspection

#### Generic Function &accessor-method-slotdef;

`(&accessor-method-slotdef; &method-r;)`

This accessor can only be called on accessor methods. It returns the &dsdmo; that defined this method. This is the value of the &slotdef-k; initialization argument associated with the method during initialization.

The specified methods for the accessor &m-mo; readers

`(&accessor-method-slotdef; (&method-r; &standard-accessor-method-t;))`
  &no-extra-spec;

### Customization

#### Generic Function &reader-method-class;

Syntax

  `(&reader-method-class; &class-r; &dsd-r; &rest-amp; &initargs-r;)`

Arguments
  &class-mo-arg;
  &dsd-r;

    a &dsdmo;.

  &initargs-r;

    alternating initialization argument names and values.

Value
&a-cmo;
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 &standard-reader-method-t;.

  The &initargs-r; argument must be the same as will be passed to &make-instance; to create the reader method. The &initargs-r; must include &slotdef-k; with &slotdef-r; as its value.

Methods

`(&reader-method-class; (&class-r; &standard-class;) (&dsd-r; &standard-dsd-t;) &rest-amp; &initargs-r;)`
`(&reader-method-class; (&class-r; &funcallable-standard-class;) (&dsd-r; &standard-dsd-t;) &rest-amp; &initargs-r;)`

  These methods return the class &standard-reader-method-t;.

  &overridables;

#### Generic Function &writer-method-class;

Syntax

  `(&writer-method-class; &class-r; direct-slot &rest-amp; &initargs-r;)`

Arguments
  &class-mo-arg;
  direct-slot

    a &dsdmo;.

  &initargs-r;

    a list of initialization arguments and values.

Value
&a-cmo;
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 &standard-writer-method-t;.

  The &initargs-r; argument must be the same as will be passed to &make-instance; to create the reader method. The &initargs-r; must include &slotdef-k; with &slotdef-t; as its value.

Methods

`(&writer-method-class; (&class-r; &standard-class;) (direct-slot &standard-dsd-t;) &rest-amp; &initargs-r;)`
`(&writer-method-class; (&class-r; &funcallable-standard-class;) (direct-slot &standard-dsd-t;) &rest-amp; &initargs-r;)`

  These methods return the class &standard-writer-method-t;.

  &overridables;

## Specializers

### Inheritance Structure of Specializer Metaobject Classes

Inheritance structure of specializer metaobject classes

### Introspection

#### Function &eql-specializer-object;

Syntax

  `(&eql-specializer-object; eql-specializer)`

Arguments
  eql-specializer

    an &eql-t; specializer metaobject.

Value
&an-object;
Purpose

  This function returns the object associated with eql-specializer during initialization. The value is guaranteed to be &eql-t; to the value originally passed to &intern-eql-specializer;, but it is not necessarily &eq; to that value.

  This function &sig-err; if eql-specializer is not an &eql-t; specializer.

### Initialization

#### Function &intern-eql-specializer;

Syntax

  `(&intern-eql-specializer; &object-r;)`

Arguments
  &object-r;

    any Lisp object.

Values

  The &eql-t; specializer metaobject for &object-r;.

Purpose

  This function returns the unique &eql-t; specializer metaobject for &object-r;, creating one if necessary. Two calls to &intern-eql-specializer; with &eql-t; arguments will return the same (i.e., &eq;) value.

Remarks

The result of calling &eql-specializer-object; on the result of a call to &intern-eql-specializer; is only guaranteed to be &eql-t; to the original &object-r; argument, not necessarily &eq;.

### Updating Dependencies

#### Generic Function &specializer-direct-methods;

Syntax

  `(&specializer-direct-methods; &specializer-r;)`

Arguments
  &specializer-mo-arg;
Value

  A possibly empty list of &m-mo;s.

Purpose

  This generic function returns the possibly empty set of those methods, connected to generic functions, which have &specializer-r; as a specializer. The elements of this set are &m-mo;s. This value is maintained by the generic functions &add-direct-method; and &remove-direct-method;.

Methods

`(&specializer-direct-methods; (&specializer-r; &class;))`
  &no-extra-spec;

  &also-must-override;

  - `&add-direct-method; (&class; &method-t;)`

  - `&remove-direct-method; (&class; &method-t;)`

  - `&specializer-direct-gfs; (&class;)`

`(&specializer-direct-methods; (&specializer-r; &eql-specializer-t;))`
  &no-extra-spec;

#### Generic Function &specializer-direct-gfs;

Syntax

  `(&specializer-direct-gfs; &specializer-r;)`

Arguments
  &specializer-mo-arg;
Value

  A possibly empty list of &gfmo;s.

Purpose

  This generic function returns the possibly empty set of those generic functions which have a method with &specializer-r; as a specializer. The elements of this set are &gfmo;s. This value is maintained by the generic functions &add-direct-method; and &remove-direct-method;.

Methods

`(&specializer-direct-gfs; (&specializer-r; &class;))`
  &no-extra-spec;

  &also-must-override;

  - `&add-direct-method; (&class; &method-t;)`

  - `&remove-direct-method; (&class; &method-t;)`

  - `&specializer-direct-methods; (&class;)`

`(&specializer-direct-gfs; (&specializer-r; &eql-specializer-t;))`
  &no-extra-spec;

#### Generic Function &add-direct-method;

Syntax

  `(&add-direct-method; &specializer-r; &method-r;)`

Arguments
  &specializer-mo-arg; &method-mo-arg;
&values-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-r; is already in the set, it is not added again (no &err-sig;).

  This set can be accessed as a list by calling the generic function &specializer-direct-methods;. Methods are removed from the set by &remove-direct-method;.

  The generic function &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-r; argument is not one of the specializers of the &method-r; argument.

Methods

`(&add-direct-method; (&specializer-r; &class;) (&method-r; &method-t;))`

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

  &no-extra-spec;

  &also-must-override;

  - `&remove-direct-method; (&class; &method-t;)`

  - `&specializer-direct-gfs; (&class;)`

  - `&specializer-direct-methods; (&class;)`

`(&add-direct-method; (&specializer-r; &eql-specializer-t;) (&method-r; &method-t;))`

  This method implements the behavior of the generic function for &eql-t; specializers.

  &no-extra-spec;

#### Generic Function &remove-direct-method;

Syntax

  `(&remove-direct-method; &specializer-r; &method-r;)`

Arguments
  &specializer-mo-arg; &method-mo-arg;
&values-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-r; is in the set it is removed. If it is not, no &err-sig;.

  This set can be accessed as a list by calling the generic function &specializer-direct-methods;. Methods are added to the set by &add-direct-method;.

  The generic function &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-r; argument is not one of the specializers of the &method-r; argument.

Methods

`(&remove-direct-method; (&specializer-r; &class;) (&method-r; &method-t;))`

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

  &no-extra-spec;

  &also-must-override;

  - `&add-direct-method; (&class; &method-t;)`

  - `&specializer-direct-gfs; (&class;)`

  - `&specializer-direct-methods; (&class;)`

`(&remove-direct-method; (&specializer-r; &eql-specializer-t;) (&method-r; &method-t;))`

  This method implements the behavior of the generic function for &eql-t; specializers.

  &no-extra-spec;

## Method Combinations

### Inheritance Structure of &mcmo; Classes

Inheritance structure of method combination metaobject classes

### Customization

#### Generic Function &find-method-combination;

Syntax

  `(&find-method-combination; &gf-r; method-combination-type-name method-combination-options)`

Arguments
  &gf-mo-arg;
  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.

Value

  A &mcmo;.

Purpose

  This generic function is called to determine the method combination object used by a generic function.

Remarks

Further details of &mcmo;s are not specified.

## Slot Access

### 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 &esdmo;, 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-r; argument, which always immediately precedes the &object-r; argument.

The correspondence between slot access function and underlying slot access generic function

Slot Access Function | Corresponding Slot Access Generic Function
--- | ---
&slot-value; &object-r; &slot-name-r; | &slot-value-UC; &class-r; &object-r; &slot-r;
&setf-slot-value; &nval-r; &object-r; &slot-name-r; | &setf-slot-value-UC; &nval-r; &class-r; &object-r; &slot-r;
&slot-boundp; &object-r; &slot-name-r; | &slot-boundp-UC; &class-r; &object-r; &slot-r;
&slot-makunbound; &object-r; &slot-name-r; | &slot-makunbound-UC; &class-r; &object-r; &slot-r;

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-k; and type &t-t;. These are called directly accessible slots .

slot directly accessible

The relevant specified around-method on &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 &esdmo;. The location can be accessed by calling the &slotdef-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 &compute-slots; is described as a list rather than a set.)

slot location

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 &standard-instance-access;. For &funcallable-standard-class;, this accessor is the function &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 &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 &c-mo; 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)))

&clisp-only;

You cannot assume that the slot-location values start at 0. In class point, for example, &x-r; and &y-r; 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.

### Funcallable Instances

Instances of classes which are themselves instances of &funcallable-standard-class; or one of its subclasses are called funcallable instances. Funcallable instances can only be created by `&allocate-instance; (&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 &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-amp;)
      (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)

### Customization

#### Function &standard-instance-access;

Syntax

  `(&standard-instance-access; &instance-r; &location-r;)`

Arguments
  &instance-r;
  &an-object;
  &location-r;

    a slot location

Value
&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-r; argument must be a standard instance (it must have been returned by `&allocate-instance;(&standard-class;)`).

  - The &instance-r; argument cannot be an non-updated obsolete instance.

  - The &location-r; argument must be a location of one of the directly accessible slots of the instance's class.

  - The slot must be bound.

  &else-undefined;

&clisp-only;

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-k;.

#### Function &funcallable-standard-instance-access;

Syntax

  `(&funcallable-standard-instance-access; &instance-r; &location-r;)`

Arguments
  &instance-r;
  &an-object;
  &location-r;

    a slot location

Value
&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-r; argument must be a funcallable instance (it must have been returned by `&allocate-instance; (&funcallable-standard-class;)`).

  - The &instance-r; argument cannot be an non-updated obsolete instance.

  - The &location-r; argument must be a location of one of the directly accessible slots of the instance's class.

  - The slot must be bound.

  &else-undefined;

&clisp-only;

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-k;.

#### Function &set-funcallable-instance-function;

Syntax

  `(&set-funcallable-instance-function; funcallable-instance &func-r;)`

Arguments
  funcallable-instance

    a funcallable instance (it must have been returned by `&allocate-instance; (&funcallable-standard-class;)`).

  &func-r;

    A function.

&values-unspecified;
Purpose

  This function is called to set or to change the function of a funcallable instance. After &set-funcallable-instance-function; is called, any subsequent calls to funcallable-instance will run the new function.

#### Generic Function &slot-value-UC;

Syntax

  `(&slot-value-UC; &class-r; &object-r; &slot-r;)`

Arguments
  &class-obj-slot-arg;
Values
&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-r; as its first argument and the pertinent &esdmo; as its third argument.

  The generic function &slot-value-UC; returns the value contained in the given slot of the given object. If the slot is unbound, &slot-unbound; is called.

  &class-slot-UC-consistent;

Methods

`(&slot-value-UC; (&class-r; &standard-class;) &object-r; (&slot-r; &standard-esd-t;))`
`(&slot-value-UC; (&class-r; &funcallable-standard-class;) &object-r; (&slot-r; &standard-esd-t;))`
  &class-slot-alloc-inst-class; &may-override;
`(&slot-value-UC; (&class-r; &built-in-class;) &object-r; &slot-r;)`

  This method &sig-err;.

#### Generic Function &setf-slot-value-UC;

Syntax

  `(&setf-slot-value-UC; &nval-r; &class-r; &object-r; &slot-r;)`

Arguments
  &nval-r;
  &an-object; &class-obj-slot-arg;
Value

  The &nval-r; argument.

Purpose

  The generic function &setf-slot-value-UC; implements the behavior of the &setf-slot-value; function. It is called by &setf-slot-value; with the class of &object-r; as its second argument and the pertinent &esdmo; as its fourth argument.

  The generic function &setf-slot-value-UC; sets the value contained in the given slot of the given object to the given new value; any previous value is lost.

  &class-slot-UC-consistent;

Methods

`(&setf-slot-value-UC; &nval-r; (&class-r; &standard-class;) &object-r; (&slot-r; &standard-esd-t;))`
`(&setf-slot-value-UC; &nval-r; (&class-r; &funcallable-standard-class;) &object-r; (&slot-r; &standard-esd-t;))`
  &class-slot-alloc-inst-class; &may-override;
`(&setf-slot-value-UC; &nval-r; (&class-r; &built-in-class;) &object-r; &slot-r;)`

  This method &sig-err;.

#### Generic Function &slot-boundp-UC;

Syntax

  `(&slot-boundp-UC; &class-r; &object-r; &slot-r;)`

Arguments
  &class-obj-slot-arg;
Value

  &boolean-t;

Purpose

  This generic function implements the behavior of the &slot-boundp; function. It is called by &slot-boundp; with the class of &object-r; as its first argument and the pertinent &esdmo; as its third argument.

  The generic function &slot-boundp-UC; tests whether a specific slot in an instance is bound.

  &class-slot-UC-consistent;

Methods

`(&slot-boundp-UC; (&class-r; &standard-class;) &object-r; (&slot-r; &standard-esd-t;))`
`(&slot-boundp-UC; (&class-r; &funcallable-standard-class;) &object-r; (&slot-r; &standard-esd-t;))`
  &class-slot-alloc-inst-class; &may-override;
`(&slot-boundp-UC; (&class-r; &built-in-class;) &object-r; &slot-r;)`

  This method &sig-err;.

Remarks

In cases where the &c-mo; class does not distinguish unbound slots, true should be returned.

#### Generic Function &slot-makunbound-UC;

Syntax

  `(&slot-makunbound-UC; &class-r; &object-r; &slot-r;)`

Arguments
  &class-obj-slot-arg;
Value

  The &object-r; argument.

Purpose

  This generic function implements the behavior of the &slot-makunbound; function. It is called by &slot-makunbound; with the class of &object-r; as its first argument and the pertinent &esdmo; as its third argument.

  The generic function &slot-makunbound-UC; restores a slot in an object to its unbound state. The interpretation of restoring a slot to its unbound state depends on the &c-mo; class.

  &class-slot-UC-consistent;

Methods

`(&slot-makunbound-UC; (&class-r; &standard-class;) &object-r; (&slot-r; &standard-esd-t;))`
`(&slot-makunbound-UC; (&class-r; &funcallable-standard-class;) &object-r; (&slot-r; &standard-esd-t;))`
  &class-slot-alloc-inst-class; &may-override;
`(&slot-makunbound-UC; (&class-r; &built-in-class;) &object-r; &slot-r;)`

  This method &sig-err;.

## Dependent Maintenance

It is convenient for portable metaobjects to be able to memoize information about other metaobjects, portable or otherwise. Because class and &gfmo;s can be reinitialized, and &gfmo;s 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 &gfmo;. The dependents of class and &gfmo;s are maintained with &add-dependent; and &remove-dependent;. The dependents of a class or &gfmo; can be accessed with &map-dependents;. Dependents are notified about a modification by calling &update-dependent;. (See the specification of &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 &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-amp; 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-amp; args)
      (declare (ignore args))
      (flush-cache (dependent updater)))

### Protocol

#### Generic Function &update-dependent;

Syntax

  `(&update-dependent; &metaobject-r; &dependent-r; &rest-amp; &initargs-r;)`

Arguments
  &metaobject-r;

    a &c-mo; or a &gfmo; - the metaobject being reinitialized or otherwise modified.

  &dependent-r;

    an object - the dependent being updated.

  &initargs-r;

    a list of the initialization arguments for the metaobject redefinition.

&values-unspecified;
Purpose

  This generic function is called to update a dependent of &metaobject-r;.

  When a class or a generic function is reinitialized each of its dependents is updated. The &initargs-r; argument to &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-r; 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-r; argument is a list of two elements: the symbol &remove-method;, and the method that was removed.

  In each case, &map-dependents; is used to call &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:

      (&map-dependents; &gf-r;
                           #'(lambda (dep)
                               (&update-dependent; &gf-r;
                                                      dep 'add-method new-method)))

&see-dep-maint;

#### Generic Function &add-dependent;

Syntax

  `(&add-dependent; &metaobject-r; &dependent-r;)`

Arguments
  &mo-gfmo;
  &dependent-r;
  &an-object;
&values-unspecified;
Purpose

  This generic function adds &dependent-r; to the dependents of &metaobject-r;. If &dependent-r; is already in the set of dependents it is not added again (no &err-sig;).

  The generic function &map-dependents; can be called to access the set of dependents of a class or generic function. The generic function &remove-dependent; can be called to remove an object from the set of dependents of a class or generic function. The effect of calling &add-dependent; or &remove-dependent; while a call to &map-dependents; on the same class or generic function is in progress is unspecified.

  The situations in which &add-dependent; is called are not specified.

Methods

`(&add-dependent; (&class-r; &standard-class;) &dependent-r;)`
  &no-extra-spec;

  &also-must-override;

  - `&remove-dependent; (&standard-class; &t-t;)`

  - `&map-dependents; (&standard-class; &t-t;)`

`(&add-dependent; (&class-r; &funcallable-standard-class;) &dependent-r;)`
  &no-extra-spec;

  &also-must-override;

  - `&remove-dependent; (&funcallable-standard-class; &t-t;)`

  - `&map-dependents; (&funcallable-standard-class; &t-t;)`

`(&add-dependent; (&gf-r; &standard-generic-function-t;) &dependent-r;)`
  &no-extra-spec;

  &also-must-override;

  - `&remove-dependent; (&standard-generic-function-t; &t-t;)`

  - `&map-dependents; (&standard-generic-function-t; &t-t;)`

&see-dep-maint;

#### Generic Function &remove-dependent;

Syntax

  `(&remove-dependent; &metaobject-r; &dependent-r;)`

Arguments
  &mo-gfmo;
  &dependent-r;
  &an-object;
&values-unspecified;
Purpose

  This generic function removes &dependent-r; from the dependents of &metaobject-r;. If &dependent-r; is not one of the dependents of &metaobject-r;, no &err-sig;.

  The generic function &map-dependents; can be called to access the set of dependents of a class or generic function. The generic function &add-dependent; can be called to add an object from the set of dependents of a class or generic function. The effect of calling &add-dependent; or &remove-dependent; while a call to &map-dependents; on the same class or generic function is in progress is unspecified.

  The situations in which &remove-dependent; is called are not specified.

Methods

`(&remove-dependent; (&class-r; &standard-class;) &dependent-r;)`
  &no-extra-spec;

  &also-must-override;

  - `&add-dependent; (&standard-class; &t-t;)`

  - `&map-dependents; (&standard-class; &t-t;)`

`(&remove-dependent; (&class-r; &funcallable-standard-class;) &dependent-r;)`
  &no-extra-spec;

  &also-must-override;

  - `&add-dependent; (&funcallable-standard-class; &t-t;)`

  - `&map-dependents; (&funcallable-standard-class; &t-t;)`

`(&remove-dependent; (&class-r; &standard-generic-function-t;) &dependent-r;)`
  &no-extra-spec;

  &also-must-override;

  - `&add-dependent; (&standard-generic-function-t; &t-t;)`

  - `&map-dependents; (&standard-generic-function-t; &t-t;)`

&see-dep-maint;

#### Generic Function &map-dependents;

Syntax

  `(&map-dependents; &metaobject-r; &func-r;)`

Arguments
  &mo-gfmo;
  &func-r;

    a function which accepts one argument.

&values-unspecified;
Purpose

  This generic function applies &func-r; to each of the dependents of &metaobject-r;. The order in which the dependents are processed is not specified, but &func-r; is applied to each dependent once and only once. If, during the mapping, &add-dependent; or &remove-dependent; is called to alter the dependents of &metaobject-r;, it is not specified whether the newly added or removed dependent will have &func-r; applied to it.

Methods

`(&map-dependents; (&metaobject-r; &standard-class;) &func-r;)`
  &no-extra-spec;

  &also-must-override;

  - `&add-dependent; (&standard-class; &t-t;)`

  - `&remove-dependent; (&standard-class; &t-t;)`

`(&map-dependents; (&metaobject-r; &funcallable-standard-class;) &func-r;)`
  &no-extra-spec;

  &also-must-override;

  - `&add-dependent; (&funcallable-standard-class; &t-t;)`

  - `&remove-dependent; (&funcallable-standard-class; &t-t;)`

`(&map-dependents; (&metaobject-r; &standard-generic-function-t;) &func-r;)`
  &no-extra-spec;

  &also-must-override;

  - `&add-dependent; (&standard-generic-function-t; &t-t;)`

  - `&remove-dependent; (&standard-generic-function-t; &t-t;)`

&see-dep-maint;

## Deviations from &amop;

This section lists the differences between the &amop; and the &clisp; implementation thereof.

Not implemented in &clisp;

- The generic function &make-method-lambda; is not implemented. See .

Features implemented differently in &clisp;

- The class precedence list of &funcallable-standard-object-t; is different. See .

- The &defclass; macro passes default values to &ensure-class;. See .

- The &defgeneric; macro passes default values to &ensure-gf;. See .

- The class &forward-referenced-class; is implemented differently. See .

- The function &gf-argument-precedence-order; &sig-err; if the generic function has no &lalist;.

- It is not possible to create a class with metaclass &standard-class; when specifying a superclass with metaclass &funcallable-standard-class;, even though &validate-superclass; returns &t; for this situation.

Extensions specific to &clisp;

- The &mop; is applicable to classes of type &structure-class;. The default superclass for &structure-class; instances is &structure-object-t;. Structure classes do not support multiple inheritance and reinitialization. See . See also .

- The &defgeneric; macro supports user-defined options. See .

- The class &method-t; is subclassable. See .

- Slot names like &nil; and &t; are allowed. See .

- The &validate-superclass; method is more permissive by default and does not need to be overridden in some obvious cases. See .

- New generic function &compute-dsd-initargs;. It can sometimes be used when overriding &dsd-class; is cumbersome.

- New generic function &compute-esd-initargs;. It can sometimes be used when overriding &esd-class; is cumbersome.

- New function &compute-effective-method-as-function;. It can be used in overriding methods of &compute-discriminating-function;.

- The generic function &ensure-gf-UC; accepts a &declare-k; keyword.

- The functions &funcallable-standard-instance-access; and &standard-instance-access; support non-updated obsolete instances and also support slots with allocation &class-k;.

- The existence of the function &class-direct-subclasses; does not prevent otherwise unreferenced classes from being &gc;ed.

### Warning CLOS:CLOS-WARNING

When &clisp; encounters suspicious or suboptimal &clos; code, it issues a &warning-t; of type CLOS:CLOS-WARNING or a &style-warning-t; of type CLOS:CLOS-STYLE-WARNING. To suppress the undesired warnings (¬-e; recommended!) use &set-global-handler; with &muffle-warning; on the appropriate &warning-t; type;. To find where the warnings come from (recommended), set &break-on-signals-var; to the appropriate &warning-t; type.

#### Warning CLOS:GF-ALREADY-CALLED-WARNING

This is a hint that the order in which program files are loaded (order of definitions, order of macro expansions, or similar) may be wrong. Example:

    (defclass ware () ((title :initarg :title :accessor title)))
    (defclass book (ware) ())
    (defclass compact-disk (ware) ())
    (defclass dvd (ware) ())
    (defgeneric add-to-inventory (object))
    (defmethod add-to-inventory ((object ware)) nil)
    (add-to-inventory (make-instance 'book :title "CLtL1"))
    (defvar *book-counter* 0)
    (defmethod add-to-inventory ((object book)) (incf *book-counter*))
    (add-to-inventory (make-instance 'book :title "CLtL2"))
    *book-counter*
    1

Since &cltl1; and &cltl2; were already added to the inventory, the programmer might have expected that `*book-counter*` is 2.

No warning for standard generic functions

A few functions, such as &print-object;, are listed in the &ansi-cl; and the &amop; as standard generic functions, to which users may add methods. This warning is ¬-e; issued for such functions.

&clos-style-warn;

##### Motivation

A generic function is defined by a contract. Whoever adds a method to a generic function, however, also expects the contract to be fulfilled. (In the example above, the contract is that `*book-counter*` equals the number of invocations of `add-to-inventory` on book instances.) If the generic function has already been called before the method was added, the method's contract is definitely broken. Maybe the programmer has foreseen this case (in this example: he could initialize `*book-counter*` to the number of instances of book that exist at this moment, rather than to &zero;), or maybe not. This is what the warning is about.

##### Disabling the warning for a specific generic function

If your generic function constitutes a public interface which is used by adding methods (similar to aforementioned &print-object;), you can declare it as such:

    (defgeneric my-public-gf (a b c)
      (declare (clos:dynamically-modifiable))
      ...)

#### Warning CLOS:GF-REPLACING-METHOD-WARNING

This is a hint that different parts of the program, possibly developed by independent people, are colliding. Example: in addition to the code above:

    (defvar *book-sales-statistics* (make-hash-table :test 'equal))
    (defmethod add-to-inventory ((object book))
      (setf (gethash (title object) sale-stats) (cons 0 0)))
    (add-to-inventory (make-instance 'book :title "AMOP"))
    *book-counter*
    1
    *book-sales-statistics*
    #S(HASH-TABLE :TEST FASTHASH-EQUAL ("AMOP" . (0 . 0)))

The programmer who programmed the first ``add-to-inventory`@book` method expects that `*book-counter*` will be incremented. The programmer who programmed the second ``add-to-inventory`@book` method expects that `*book-sales-statistics*` gets augmented. If the implementation gives no warning, one of the two programmers will waste time debugging. &clos-style-warn;

##### Motivation

This warning can be warranted for the same reason as above: if the old method and the new method have a different contract, something is fishy and possibly wrong. Additionally, the programmers may not even have intended to replace the method. They may have intended cumulative effects of the two methods.

#### Warning CLOS:CLASS-OBSOLESCENCE-WARNING

This is a hint that different parts of the program define the same &class; incompatibly, and some objects, created to the old specification, have been obsoleted by the new one. Example: in addition to the code above:

    (defclass ware ()
      ((title :initarg :title :accessor title)
       (year :initarg :year :accessor year)))

Evaluating the above will obsolete all objects of type wares, books etc created so far, i.e., their components will become inaccessible. &clos-style-warn;

##### Motivation

In addition to the above, this warning tells the programmers that they are losing some objects they have already created.