The reader generic functions which simply return information associated with method metaobjects are presented together here in the format described in Section 29.3.3, “Introspection: Readers for class metaobjects”.
Each of these reader generic functions have the same syntax,
accepting one required argument called method
, which must be a
method metaobject; otherwise, an ERROR
is SIGNAL
ed. An ERROR
is also SIGNAL
ed
if the method metaobject has not been initialized.
These generic functions can be called by the user or the implementation.
For any of these generic functions which returns a list, such lists will not be mutated by the implementation. The results are undefined if a portable program allows such a list to be mutated.
CLOS:METHOD-SPECIALIZERS
(CLOS:METHOD-SPECIALIZERS
method
)
Returns a list of the specializers of method
. This value is a
list of specializer metaobjects. This is the value of the
:SPECIALIZERS
initialization argument that was associated with the
method during initialization.
METHOD-QUALIFIERS
(METHOD-QUALIFIERS
method
)
Returns a (possibly empty) list of the qualifiers of method
.
This value is a list of non-NIL
atoms. This is the defaulted value of
the :QUALIFIERS
initialization argument that was associated with the
method during initialization.
CLOS:METHOD-LAMBDA-LIST
(CLOS:METHOD-LAMBDA-LIST
method
)
Returns the (unspecialized) lambda list of method
. This value
is a Common Lisp lambda list. This is the value of the :LAMBDA-LIST
initialization argument that was associated with the method during
initialization.
CLOS:METHOD-GENERIC-FUNCTION
(CLOS:METHOD-GENERIC-FUNCTION
method
)
Returns the generic function that method
is currently
connected to, or NIL
if it is not currently connected to any generic
function. This value is either a generic function metaobject or NIL
.
When a method is first created it is not connected to any generic
function. This connection is maintained by the generic functions
ADD-METHOD
and REMOVE-METHOD
.
CLOS:METHOD-FUNCTION
(CLOS:METHOD-FUNCTION
method
)
Returns the method function of method
. This is the
value of the :FUNCTION
initialization argument that was associated
with the method during initialization.
The specified methods for the method metaobject readers
(CLOS:METHOD-SPECIALIZERS
(method
STANDARD-METHOD
))
(METHOD-QUALIFIERS
(method
STANDARD-METHOD
))
(CLOS:METHOD-LAMBDA-LIST
(method
STANDARD-METHOD
))
(CLOS:METHOD-FUNCTION
(method
STANDARD-METHOD
))
(CLOS:METHOD-GENERIC-FUNCTION
(method
STANDARD-METHOD
))
No behavior is specified for this method beyond that which is specified for the generic function.
The value returned by this method is maintained by
and
ADD-METHOD
(STANDARD-GENERIC-FUNCTION
STANDARD-METHOD
)
.REMOVE-METHOD
(STANDARD-GENERIC-FUNCTION
STANDARD-METHOD
)
DEFMETHOD
The evaluation or execution of a DEFMETHOD
form requires first
that the body of the method be converted to a method function.
This process is described
below.
The result of this process is a method function and a set of additional
initialization arguments to be used when creating the new method.
Given these two values, the evaluation or execution of a DEFMETHOD
form proceeds in three steps.
The first step ensures the existence of a generic function with
the specified name. This is done by calling the function ENSURE-GENERIC-FUNCTION
.
The first argument in this call is the generic function name specified
in the DEFMETHOD
form.
The second step is the creation of the new method metaobject by calling
MAKE-INSTANCE
. The class of the new method metaobject is determined by calling
CLOS:GENERIC-FUNCTION-METHOD-CLASS
on the result of the call to ENSURE-GENERIC-FUNCTION
from the
first step.
The initialization arguments received by the call to MAKE-INSTANCE
are as follows:
:QUALIFIERS
initialization
argument is a list of the qualifiers which appeared in the DEFMETHOD
form. No special processing is done on these values. The order of the
elements of this list is the same as in the DEFMETHOD
form.
:LAMBDA-LIST
initialization
argument is the unspecialized lambda list from the DEFMETHOD
form.
:SPECIALIZERS
initialization
argument is a list of the specializers for the method. For specializers
which are classes, the specializer is the class metaobject itself. In
the case of EQL
specializers, it will be an CLOS:EQL-SPECIALIZER
metaobject obtained by calling CLOS:INTERN-EQL-SPECIALIZER
on the result of
evaluating the EQL
specializer form in the lexical environment of the
DEFMETHOD
form.:FUNCTION
initialization
argument is the method function.The value of the :DECLARATIONS
initialization
argument is a list of the declaration specifiers from the DEFMETHOD
form.
If there are no declarations in the macro form, this initialization argument
either does not appear, or appears with a value of the empty list.
No :DECLARATIONS
initialization argument is
provided, because method initialization does not support a :DECLARATIONS
argument, and because the method function is already completely provided
through the :FUNCTION
initialization argument.
:DOCUMENTATION
initialization
argument is the documentation string from the DEFMETHOD
form. If
there is no documentation string in the macro form this initialization
argument either does not appear, or appears with a value of false.
In the third step, ADD-METHOD
is called to add the newly created
method to the set of methods associated with the generic function metaobject.
The result of the call to ADD-METHOD
is returned as the result
of evaluating or executing the DEFMETHOD
form.
An example showing a typical DEFMETHOD
form and a sample
expansion is shown in the following example:
An example DEFMETHOD
form and one possible correct
expansion. In the expansion, method-lambda
is the result of calling CLOS:MAKE-METHOD-LAMBDA
as described in
Section 29.6.3.1.1, “Processing Method Bodies”.
The initargs appearing after :FUNCTION
are assumed to be additional
initargs returned from the call to CLOS:MAKE-METHOD-LAMBDA
.
(defmethod move :before ((p position) (l (eql 0))&OPTIONAL
(visiblyp t)&KEY
color) (set-to-origin p) (when visiblyp (show-move p 0 color))) (let ((#:g001 (ensure-generic-function 'move))) (add-method #:g001 (make-instance (generic-function-method-class #:g001) :qualifiers '(:before) :specializers (list (find-class 'position) (intern-eql-specializer 0)) :lambda-list '(p l&OPTIONAL
(visiblyp t)&KEY
color) :function (functionmethod-lambda
) 'additional-initarg-1 't 'additional-initarg-2 '39)))
The processing of the method body for this method is shown below.
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
option of DEFGENERIC
forms. Initial methods are
not considered by any of the protocols specified in this document.
During macro-expansion of the DEFMETHOD
macro shown in
the previous example code
similar to this would be run to produce the method lambda and
additional initargs. In this example, environment
is the macroexpansion
environment of the DEFMETHOD
macro form.
(let ((gf (ensure-generic-function 'move))) (make-method-lambda gf (class-prototype (generic-function-method-class gf)) '(lambda (p l&OPTIONAL
(visiblyp t)&KEY
color) (set-to-origin p) (when visiblyp (show-move p 0 color)))environment
))
The first step occurs during macro-expansion of the macro form. In this step, the method lambda list, declarations and body are converted to a lambda expression called a method lambda . This conversion is based on information associated with the generic function definition in effect at the time the macro form is expanded.
The generic function definition is obtained by calling ENSURE-GENERIC-FUNCTION
with
a first argument of the generic function name specified in the macro form.
The :LAMBDA-LIST
keyword argument is not passed in this call.
Given the generic function, production of the method lambda
proceeds by calling CLOS:MAKE-METHOD-LAMBDA
.
The first argument in this call is the generic function obtained as
described above.
The second argument is the result of calling CLOS:CLASS-PROTOTYPE
on the
result of calling CLOS:GENERIC-FUNCTION-METHOD-CLASS
on the generic function.
The third argument is a lambda expression formed from the method lambda list,
declarations and body.
The fourth argument is the macro-expansion environment of the macro
form; this is the value of the &ENVIRONMENT
argument to the
DEFMETHOD
macro.
The generic function CLOS:MAKE-METHOD-LAMBDA
returns two values.
The first is the method lambda itself.
The second is a list of initialization arguments and values. These are
included in the initialization arguments when the method is created.
In the second step, the method lambda is converted to a function
which properly captures the lexical scope of the macro form. This is
done by having the method lambda appear in the macro-expansion as the
argument of the FUNCTION
special form. During the subsequent
evaluation of the macro-expansion, the result of the FUNCTION
special
form is the method function.
See The generic function CLOS:MAKE-METHOD-LAMBDA
is not implemented.
An example of creating a generic function and a method metaobject, and then adding the method to the generic function is shown below. This example is comparable to the method definition shown above:
(let* ((gf (make-instance 'standard-generic-function :lambda-list '(p l&OPTIONAL
visiblyp&KEY
))) (method-class (generic-function-method-class gf))) (multiple-value-bind (lambda initargs) (make-method-lambda gf (class-prototype method-class) '(lambda (p l&OPTIONAL
(visiblyp t)&KEY
color) (set-to-origin p) (when visiblyp (show-move p 0 color))) nil) (add-method gf (apply #'make-instance method-class :function (compile nil lambda) :specializers (list (find-class 'position) (intern-eql-specializer 0)) :qualifiers () :lambda-list '(p l&OPTIONAL
(visiblyp t)&KEY
color) initargs))))
Methods created through DEFMETHOD
have a faster calling
convention than methods created through a portable MAKE-INSTANCE
invocation.
A method metaobject can be created by calling MAKE-INSTANCE
.
The initialization arguments establish the definition of the method.
A method metaobject cannot be redefined;
calling REINITIALIZE-INSTANCE
SIGNAL
s an ERROR
.
Initialization of a method metaobject must be done by calling MAKE-INSTANCE
and allowing it to call INITIALIZE-INSTANCE
. Portable programs must
not
INITIALIZE-INSTANCE
directly to
initialize a method metaobject;SHARED-INITIALIZE
directly to
initialize a method metaobject;CHANGE-CLASS
to change the class of any
method metaobject or to turn a non-method object into a method metaobject.
Since metaobject classes may not be redefined,
no behavior is specified for the result of calls to
UPDATE-INSTANCE-FOR-REDEFINED-CLASS
on method metaobjects.
Since the class of a method metaobject cannot be changed,
no behavior is specified for the result of calls to
UPDATE-INSTANCE-FOR-DIFFERENT-CLASS
on method metaobjects.
During initialization, each initialization argument is checked for errors and then associated with the method metaobject. The value can then be accessed by calling the appropriate accessor as shown in Table 29.5, “Initialization arguments and accessors for method metaobjects”.
This section begins with a description of the error checking and processing of each initialization argument. This is followed by a table showing the generic functions that can be used to access the stored initialization arguments. The section ends with a set of restrictions on portable methods affecting method metaobject initialization.
In these descriptions, the phrase “this argument defaults to
value
” means that when that initialization argument is not
supplied, initialization is performed as if value
had been supplied.
For some initialization arguments this could be done by the use of
default initialization arguments, but whether it is done this way is not
specified. Implementations are free to define default initialization
arguments for specified method metaobject classes. Portable programs
are free to define default initialization arguments for portable
subclasses of the class METHOD
.
:QUALIFIERS
argument is a list of method
qualifiers. An ERROR
is SIGNAL
ed if this value is not a proper list, or if
any element of the list is not a non-null atom. This argument
defaults to the empty list.:LAMBDA-LIST
argument is the unspecialized
lambda list of the method. An ERROR
is SIGNAL
ed if this value is not a
proper lambda list. If this value is not supplied, an ERROR
is SIGNAL
ed.
:SPECIALIZERS
argument is a list of the
specializer metaobjects for the method. An ERROR
is SIGNAL
ed if this value
is not a proper list, or if the length of the list differs from the
number of required arguments in the :LAMBDA-LIST
argument, or if
any element of the list is not a specializer metaobject. If this
value is not supplied, an ERROR
is SIGNAL
ed.:FUNCTION
argument is a method function. It
must be compatible with the methods on CLOS:COMPUTE-EFFECTIVE-METHOD
defined for this class of method and generic function with which it
will be used. That is, it must accept the same number of arguments
as all uses of CALL-METHOD
that will call it supply. (See
CLOS:COMPUTE-EFFECTIVE-METHOD
and CLOS:MAKE-METHOD-LAMBDA
for more information.)
An ERROR
is SIGNAL
ed if this argument is not supplied.CLOS:STANDARD-ACCESSOR-METHOD
, the :SLOT-DEFINITION
initialization argument must be provided. Its value is the direct
slot definition metaobject which defines this accessor method. An ERROR
is SIGNAL
ed if the value
is not an instance of a subclass of CLOS:DIRECT-SLOT-DEFINITION
.:DOCUMENTATION
argument is a string or NIL
.
An ERROR
is SIGNAL
ed if this value is not a string or NIL
. This argument
defaults to NIL
.After the processing and defaulting of initialization arguments described above, the value of each initialization argument is associated with the method metaobject. These values can then be accessed by calling the corresponding generic function. The correspondences are as follows:
Table 29.5. Initialization arguments and accessors for method metaobjects
Initialization Argument | Generic Function |
---|---|
:QUALIFIERS | METHOD-QUALIFIERS |
:LAMBDA-LIST | CLOS:METHOD-LAMBDA-LIST |
:SPECIALIZERS | CLOS:METHOD-SPECIALIZERS |
:FUNCTION | CLOS:METHOD-FUNCTION |
:SLOT-DEFINITION | CLOS:ACCESSOR-METHOD-SLOT-DEFINITION |
:DOCUMENTATION | DOCUMENTATION |
It is not specified which methods provide the initialization behavior described above. Instead, the information needed to allow portable programs to specialize this behavior is presented in as a set of restrictions on the methods a portable program can define. The model is that portable initialization methods have access to the method metaobject when either all or none of the specified initialization has taken effect.
These restrictions govern the methods that a portable program can
define on the generic functions INITIALIZE-INSTANCE
,
REINITIALIZE-INSTANCE
, and SHARED-INITIALIZE
. These restrictions
apply only to methods on these generic functions for which the first
specializer is a subclass of the class METHOD
. Other portable
methods on these generic functions are not affected by these
restrictions.
SHARED-INITIALIZE
or REINITIALIZE-INSTANCE
.For INITIALIZE-INSTANCE
:
The results are undefined if any of these restrictions are violated.
CLOS:EXTRACT-LAMBDA-LIST
(CLOS:EXTRACT-LAMBDA-LIST
specialized-lambda-list
)
specialized-lambda-list
DEFMETHOD
.
This function takes a specialized lambda list and returns the lambda list with the specializers removed. This is a non-destructive operation. Whether the result shares any structure with the argument is unspecified.
If the specialized-lambda-list
argument does not have legal syntax,
an ERROR
is SIGNAL
ed. This syntax checking does not check the syntax of the
actual specializer names, only the syntax of the lambda list and
where the specializers appear.
(CLOS:EXTRACT-LAMBDA-LIST
'((p position))) ⇒(P)
(CLOS:EXTRACT-LAMBDA-LIST
'((p position) x y)) ⇒(P X Y)
(CLOS:EXTRACT-LAMBDA-LIST
'(a (b (eql x)) c&REST
i)) ⇒(A B C
&OPTIONAL
I)
CLOS:EXTRACT-SPECIALIZER-NAMES
(CLOS:EXTRACT-SPECIALIZER-NAMES
specialized-lambda-list
)
specialized-lambda-list
DEFMETHOD
.
This function takes a specialized lambda list and returns its specializer names. This is a non-destructive operation. Whether the result shares structure with the argument is unspecified.
The list returned by this function will not be mutated by the implementation. The results are undefined if a portable program mutates the list returned by this function.
The result of this function will be a list with a
number of elements equal to the number of required arguments in
specialized-lambda-list
. Specializers are defaulted to the symbol T
.
If the specialized-lambda-list
argument does not have legal
syntax, an ERROR
is SIGNAL
ed. This syntax checking does not check the syntax
of the actual specializer names, only the syntax of the lambda list
and where the specializers appear.
(CLOS:EXTRACT-SPECIALIZER-NAMES
'((p position))) ⇒(POSITION)
(CLOS:EXTRACT-SPECIALIZER-NAMES
'((p position) x y)) ⇒(POSITION T T)
(CLOS:EXTRACT-SPECIALIZER-NAMES
'(a (b (eql x)) c&REST
i)) ⇒(T (EQL X) T)
These notes document CLISP version 2.49 | Last modified: 2010-07-07 |