User Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cl:macros:defmethod [2019/07/14 17:00]
cl:macros:defmethod [2019/10/19 05:00] (current)
Line 1: Line 1:
 +====== Macro DEFMETHOD ======
 +
 +====Syntax====
 +  * **defmethod** //​function-name//​ {//​method-qualifier//​}''​*''​ //​specialized-lambda-list//​} ⟦{declaration}''​*''​ | //​documentation//​⟧ {//​form//​}''​*''​ → //​new-method//​
 +
 +<​blockquote>​
 +function-name ::= {__symbol__ | ([[CL:​Macros:​setf]] __symbol__)}
 +method-qualifier ::= __non-list__
 +specialized-lambda-list ::= ({//var// | (//var// __parameter-specializer-name__)}''​*''​
 +                             ​[**&​optional** {//var// | (//var// __parameter-specializer-name__)}''​*''​]
 +                             ​[**&​rest** //var//]
 +                             ​[**&​key** {//var// | ({//var// | (__keyword__ //var//)} [//​initform//​ [//​supplied-p-parameter//​]])}''​*''​
 +                                   ​[**&​allow-other-keys**]]
 +                             ​[**&​aux** {//var// | (//var// [//​initform//​])}''​*''​])
 +parameter-specializer-name ::= __symbol__ | ([[CL:​Types:​eql]] //​eql-specializer-form//​)
 +</​blockquote>​
 +
 +====Arguments and Values====
 +  * //​declaration//​ - a **[[CL:​Symbols:​declare]]** //​[[CL:​Glossary:​expression]]//;​ not evaluated.
 +  * //​documentation//​ - a //​[[CL:​Glossary:​string]]//;​ not evaluated.
 +  * //var// - a //​[[CL:​Glossary:​variable]]//​ //​[[CL:​Glossary:​name]]//​.
 +  * //​eql-specializer-form//​ - a //​[[CL:​Glossary:​form]]//​.
 +  * //form// - a //​[[CL:​Glossary:​form]]//​.
 +  * //​initform//​ - a //​[[CL:​Glossary:​form]]//​.
 +  * //​supplied-p-parameter//​ - variable name.
 +  * //​new-method//​ - the new //​[[CL:​Glossary:​method]]//​ //​[[CL:​Glossary:​object]]//​.
 +
 +====Description====
 +The macro **defmethod** defines a //​[[CL:​Glossary:​method]]//​ on a //​[[CL:​Glossary:​generic function]]//​.
 +
 +If ''​([[CL:​Functions:​fboundp]] //​function-name//​)]]''​ is **[[CL:​Constant Variables:​nil]]**,​ a //​[[CL:​Glossary:​generic function]]//​ is created with default values for the argument precedence order (each argument is more specific than the arguments to its right in the argument list), for the generic function class (the **[[CL:​Types:​standard-generic-function]]** //​[[CL:​Glossary:​class]]//​),​ for the method class (the **[[CL:​Types:​standard-method]]** //​[[CL:​Glossary:​class]]//​),​ and for the method combination type (the standard method combination type). The //​[[CL:​Glossary:​lambda list]]// of the //​[[CL:​Glossary:​generic function]]//​ is congruent with the //​[[CL:​Glossary:​lambda list]]// of the //​[[CL:​Glossary:​method]]//​ being defined; if the **defmethod** form mentions keyword arguments, the //​[[CL:​Glossary:​lambda list]]// of the //​[[CL:​Glossary:​generic function]]//​ will mention **'':&​key''​** (but no keyword arguments). If //​function-name//​ names an //​[[CL:​Glossary:​ordinary function]]//,​ a //​[[CL:​Glossary:​macro]]//,​ or a //​[[CL:​Glossary:​special operator]]//,​ an error is signaled.
 +
 +If a //​[[CL:​Glossary:​generic function]]//​ is currently named by //​function-name//,​ the //​[[CL:​Glossary:​lambda list]]// of the //​[[CL:​Glossary:​method]]//​ must be congruent with the //​[[CL:​Glossary:​lambda list]]// of the //​[[CL:​Glossary:​generic function]]//​. If this condition does not hold, an error is signaled. For a definition of congruence in this context, see section {\secref\GFMethodLambdaListCongruency}.
 +
 +Each //​method-qualifier//​ argument is an //​[[CL:​Glossary:​object]]//​ that is used by method combination to identify the given //​[[CL:​Glossary:​method]]//​. The method combination type might further restrict what a method //​[[CL:​Glossary:​qualifier]]//​ can be. The standard method combination type allows for //​[[CL:​Glossary:​unqualified methods]]// and //​[[CL:​Glossary:​method|methods]]//​ whose sole //​[[CL:​Glossary:​qualifier]]//​ is one of the keywords **'':​before''​**,​ **'':​after''​**,​ or **'':​around''​**.
 +
 +The //​specialized-lambda-list//​ argument is like an ordinary //​[[CL:​Glossary:​lambda list]]// except that the //​[[CL:​Glossary:​names]]//​ of required parameters can be replaced by specialized parameters. A specialized parameter is a list of the form ''​(//​var//​ //​parameter-specializer-name//​)''​. Only required parameters can be specialized. If //​parameter-specializer-name//​ is a //​[[CL:​Glossary:​symbol]]//​ it names a //​[[CL:​Glossary:​class]]//;​ if it is a //​[[CL:​Glossary:​list]]//,​ it is of the form ''​([[CL:​Types:​eql]] //​eql-specializer-form//​)''​. The parameter specializer name ''​([[CL:​Types:​eql]] //​eql-specializer-form//​)''​ indicates that the corresponding argument must be **[[CL:​Functions:​eql]]** to the //​[[CL:​Glossary:​object]]//​ that is the value of //​eql-specializer-form//​ for the //​[[CL:​Glossary:​method]]//​ to be applicable.
 +
 +The //​eql-specializer-form//​ is evaluated at the time that the expansion of the **defmethod** macro is evaluated.
 +
 +If no //​[[CL:​Glossary:​parameter specializer name]]// is specified for a given required parameter, the //​[[CL:​Glossary:​parameter specializer]]//​ defaults to the **[[CL:​Types:​t]]** //​[[CL:​Glossary:​class]]//​. For further discussion, see section {\secref\IntroToMethods}.
 +
 +The //form// arguments specify the method body. The body of the //​[[CL:​Glossary:​method]]//​ is enclosed in an //​[[CL:​Glossary:​implicit block]]//. If //​function-name//​ is a //​[[CL:​Glossary:​symbol]]//,​ this block bears the same //​[[CL:​Glossary:​name]]//​ as the //​[[CL:​Glossary:​generic function]]//​. If //​function-name//​ is a //​[[CL:​Glossary:​list]]//​ of the form ''​([[CL:​Macros:​setf]] //​symbol//​)'',​ the //​[[CL:​Glossary:​name]]//​ of the block is //symbol//.
 +
 +The //​[[CL:​Glossary:​class]]//​ of the //​[[CL:​Glossary:​method]]//​ //​[[CL:​Glossary:​object]]//​ that is created is that given by the method class option of the //​[[CL:​Glossary:​generic function]]//​ on which the //​[[CL:​Glossary:​method]]//​ is defined.
 +
 +If the //​[[CL:​Glossary:​generic function]]//​ already has a //​[[CL:​Glossary:​method]]//​ that agrees with the //​[[CL:​Glossary:​method]]//​ being defined on //​[[CL:​Glossary:​parameter specializer|parameter specializers]]//​ and //​[[CL:​Glossary:​qualifier|qualifiers]]//,​ **defmethod** replaces the existing //​[[CL:​Glossary:​method]]//​ with the one now being defined. For a definition of agreement in this context. see section {\secref\SpecializerQualifierAgreement}.
 +
 +The //​[[CL:​Glossary:​parameter specializer|parameter specializers]]//​ are derived from the //​[[CL:​Glossary:​parameter specializer names]]// as described in \secref\IntroToMethods.
 +
 +The expansion of the **defmethod** macro "​refers to" each specialized parameter (see the description of **[[CL:​Declarations:​ignore]]** within the description of **[[CL:​Symbols:​declare]]**). This includes parameters that have an explicit //​[[CL:​Glossary:​parameter specializer name]]// of **[[CL:​Types:​t]]**. This means that a compiler warning does not occur if the body of the //​[[CL:​Glossary:​method]]//​ does not refer to a specialized parameter, while a warning might occur if the body of the //​[[CL:​Glossary:​method]]//​ does not refer to an unspecialized parameter. For this reason, a parameter that specializes on **[[CL:​Types:​t]]** is not quite synonymous with an unspecialized parameter in this context.
 +
 +Declarations at the head of the method body that apply to the method'​s //​[[CL:​Glossary:​lambda variables]]//​ are treated as //​[[CL:​Glossary:​bound declarations]]//​ whose //​[[CL:​Glossary:​scope]]//​ is the same as the corresponding //​[[CL:​Glossary:​bindings]]//​.
 +
 +Declarations at the head of the method body that apply to the functional bindings of **[[CL:​Functions:​call-next-method]]** or **[[CL:​Functions:​next-method-p]]** apply to references to those functions within the method body //forms//. Any outer //​[[CL:​Glossary:​bindings]]//​ of the //​[[CL:​Glossary:​function names]]// **[[CL:​Functions:​call-next-method]]** and **[[CL:​Functions:​next-method-p]]**,​ and declarations associated with such //​[[CL:​Glossary:​bindings]]//​ are //​[[CL:​Glossary:​shadowed]]//​ within the method body //forms//.
 +
 +The //​[[CL:​Glossary:​scope]]//​ of //​[[CL:​Glossary:​free declarations]]//​ at the head of the method body is the entire method body, which includes any implicit local function definitions but excludes //​[[CL:​Glossary:​initialization form|initialization forms]]// for the //​[[CL:​Glossary:​lambda variables]]//​.
 +
 +**defmethod** is not required to perform any compile-time side effects. In particular, the //​[[CL:​Glossary:​method|methods]]//​ are not installed for invocation during compilation. An //​[[CL:​Glossary:​implementation]]//​ may choose to store information about the //​[[CL:​Glossary:​generic function]]//​ for the purposes of compile-time error-checking (such as checking the number of arguments on calls, or noting that a definition for the function name has been seen).
 +
 +//​Documentation//​ is attached as a //​[[CL:​Glossary:​documentation string]]// to the //​[[CL:​Glossary:​method]]//​ //​[[CL:​Glossary:​object]]//​.
 +
 +====Examples====
 +None.
 +
 +====Affected By====
 +The definition of the referenced //​[[CL:​Glossary:​generic function]]//​.
 +
 +====Exceptional Situations====
 +If //​function-name//​ names an //​[[CL:​Glossary:​ordinary function]]//,​ a //​[[CL:​Glossary:​macro]]//,​ or a //​[[CL:​Glossary:​special operator]]//,​ an error of type **[[CL:​Types:​error]]** is signaled.
 +
 +If a //​[[CL:​Glossary:​generic function]]//​ is currently named by //​function-name//,​ the //​[[CL:​Glossary:​lambda list]]// of the //​[[CL:​Glossary:​method]]//​ must be congruent with the //​[[CL:​Glossary:​lambda list]]// of the //​[[CL:​Glossary:​generic function]]//,​ or an error of type **[[CL:​Types:​error]]** is signaled.
 +
 +====See Also====
 +  * **[[CL:​Macros:​defgeneric|Macro DEFGENERIC]]**
 +  * **[[CL:​Functions:​documentation|Generic Function DOCUMENTATION]]**
 +  * {\secref\IntroToMethods}
 +  * {\secref\GFMethodLambdaListCongruency}
 +  * {\secref\SpecializerQualifierAgreement}
 +  * {\secref\DocVsDecls}
 +
 +====Notes====
 +None.
 +
 +\issue{DECLS-AND-DOC} \issue{DEFMETHOD-DECLARATION-SCOPE:​CORRESPONDS-TO-BINDINGS} \issue{COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS:​CLARIFY} \issue{DOCUMENTATION-FUNCTION-BUGS:​FIX}