263 lines
39 KiB
HTML
263 lines
39 KiB
HTML
|
<!-- Common Lisp HyperSpec (TM), version 7.0 generated by Kent M. Pitman on Mon, 11-Apr-2005 2:31am EDT -->
|
||
|
<HTML>
|
||
|
<HEAD>
|
||
|
<TITLE>CLHS: Macro DEFINE-METHOD-COMBINATION</TITLE>
|
||
|
<LINK HREF="../Data/clhs.css" REL="stylesheet" TYPE="text/css" />
|
||
|
<META HTTP-EQUIV="Author" CONTENT="Kent M. Pitman">
|
||
|
<META HTTP-EQUIV="Organization" CONTENT="LispWorks Ltd.">
|
||
|
<LINK REL=TOP HREF="../Front/index.htm">
|
||
|
<LINK REL=COPYRIGHT HREF="../Front/Help.htm#Legal">
|
||
|
<LINK REL=DISCLAIMER HREF="../Front/Help.htm#Disclaimer">
|
||
|
<LINK REL=PREV HREF="f_comput.htm">
|
||
|
<LINK REL=UP HREF="c_object.htm">
|
||
|
<LINK REL=NEXT HREF="f_find_m.htm">
|
||
|
</HEAD>
|
||
|
<BODY>
|
||
|
<H1><A REV=MADE HREF="http://www.lispworks.com/"><IMG WIDTH=80 HEIGHT=65 ALT="[LISPWORKS]" SRC="../Graphics/LWSmall.gif" ALIGN=Bottom></A><A REL=TOP HREF="../Front/index.htm"><IMG WIDTH=237 HEIGHT=65 ALT="[Common Lisp HyperSpec (TM)]" SRC="../Graphics/CLHS_Sm.gif" ALIGN=Bottom></A> <A REL=PREV HREF="f_comput.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Previous]" SRC="../Graphics/Prev.gif" ALIGN=Bottom></A><A REL=UP HREF="c_object.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Up]" SRC="../Graphics/Up.gif" ALIGN=Bottom></A><A REL=NEXT HREF="f_find_m.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Next]" SRC="../Graphics/Next.gif" ALIGN=Bottom></A></H1>
|
||
|
|
||
|
<HR>
|
||
|
|
||
|
<A NAME="define-method-combination"><I>Macro</I> <B>DEFINE-METHOD-COMBINATION</B></A> <P>
|
||
|
<P>
|
||
|
<P><B>Syntax:</B><P>
|
||
|
<P>
|
||
|
|
||
|
<B>define-method-combination</B> <I>name [[<I>short-form-option</I>]]</I><P> => <I>name</I><P>
|
||
|
<P>
|
||
|
|
||
|
<B>define-method-combination</B> <I>name lambda-list (<I>method-group-specifier</I><B>*</B>) [(<TT>:arguments</TT> . args-lambda-list)] [(<TT>:generic-function</TT> generic-function-symbol)] [[<I>declaration</I><B>*</B> | <I>documentation</I>]] <I>form</I><B>*</B></I><P> => <I>name</I><P>
|
||
|
<P>
|
||
|
<PRE>
|
||
|
short-form-option::= :documentation documentation |
|
||
|
:identity-with-one-argument identity-with-one-argument |
|
||
|
:operator operator
|
||
|
</PRE>
|
||
|
<PRE>
|
||
|
method-group-specifier::= (name {qualifier-pattern+ | predicate} [[long-form-option]])
|
||
|
</PRE>
|
||
|
<PRE>
|
||
|
long-form-option::= :description description |
|
||
|
:order order |
|
||
|
:required required-p
|
||
|
</PRE>
|
||
|
<P>
|
||
|
<P><B>Arguments and Values:</B><P>
|
||
|
<P>
|
||
|
<I>args-lambda-list</I>---a <A REL=DEFINITION HREF="26_glo_d.htm#define-method-combination_arguments_lambda_list"><I>define-method-combination arguments lambda list</I></A>. <P>
|
||
|
<I>declaration</I>---a <A REL=DEFINITION HREF="s_declar.htm#declare"><B>declare</B></A> <A REL=DEFINITION HREF="26_glo_e.htm#expression"><I>expression</I></A>; not evaluated. <P>
|
||
|
<I>description</I>---a <A REL=DEFINITION HREF="26_glo_f.htm#format_control"><I>format control</I></A>. <P>
|
||
|
<I>documentation</I>---a <A REL=DEFINITION HREF="26_glo_s.htm#string"><I>string</I></A>; not evaluated. <P>
|
||
|
<I>forms</I>---an <A REL=DEFINITION HREF="26_glo_i.htm#implicit_progn"><I>implicit progn</I></A> that must compute and return the <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> that specifies how the <A REL=DEFINITION HREF="26_glo_m.htm#method"><I>methods</I></A> are combined, that is, the <A REL=DEFINITION HREF="26_glo_e.htm#effective_method"><I>effective method</I></A>. <P>
|
||
|
<I>generic-function-symbol</I>---a <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A>. <P>
|
||
|
<I>identity-with-one-argument</I>---a <A REL=DEFINITION HREF="26_glo_g.htm#generalized_boolean"><I>generalized boolean</I></A>. <P>
|
||
|
<I>lambda-list</I>---<A REL=DEFINITION HREF="26_glo_o.htm#ordinary_lambda_list"><I>ordinary lambda list</I></A>. <P>
|
||
|
<I>name</I>---a <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A>. Non-<A REL=DEFINITION HREF="26_glo_k.htm#keyword"><I>keyword</I></A>, <A REL=DEFINITION HREF="26_glo_n.htm#non-nil"><I>non-nil</I></A> <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbols</I></A> are usually used. <P>
|
||
|
<I>operator</I>---an <A REL=DEFINITION HREF="26_glo_o.htm#operator"><I>operator</I></A>. <I>Name</I> and <I>operator</I> are often the <A REL=DEFINITION HREF="26_glo_s.htm#same"><I>same</I></A> <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A>. This is the default, but it is not required. <P>
|
||
|
<I>order</I>---<TT>:most-specific-first</TT> or <TT>:most-specific-last</TT>; evaluated. <P>
|
||
|
<I>predicate</I>---a <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A> that names a <A REL=DEFINITION HREF="26_glo_f.htm#function"><I>function</I></A> of one argument that returns a <A REL=DEFINITION HREF="26_glo_g.htm#generalized_boolean"><I>generalized boolean</I></A>. <P>
|
||
|
<I>qualifier-pattern</I>---a <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>list</I></A>, or the <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A> <A REL=DEFINITION HREF="a_st.htm#ST"><B>*</B></A>. <P>
|
||
|
<I>required-p</I>---a <A REL=DEFINITION HREF="26_glo_g.htm#generalized_boolean"><I>generalized boolean</I></A>. <P>
|
||
|
<P><B>Description:</B><P>
|
||
|
<P>
|
||
|
The macro <A REL=DEFINITION HREF="#define-method-combination"><B>define-method-combination</B></A> is used to define new types of method combination. <P>
|
||
|
There are two forms of <A REL=DEFINITION HREF="#define-method-combination"><B>define-method-combination</B></A>. The short form is a simple facility for the cases that are expected to be most commonly needed. The long form is more powerful but more verbose. It resembles <A REL=DEFINITION HREF="m_defmac.htm#defmacro"><B>defmacro</B></A> in that the body is an expression, usually using backquote, that computes a <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A>. Thus arbitrary control structures can be implemented. The long form also allows arbitrary processing of method <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifiers</I></A>. <P>
|
||
|
<P><DL><DT><B>Short Form</B> <P><DD>
|
||
|
The short form syntax of <A REL=DEFINITION HREF="#define-method-combination"><B>define-method-combination</B></A> is recognized when the second <A REL=DEFINITION HREF="26_glo_s.htm#subform"><I>subform</I></A> is a <A REL=DEFINITION HREF="26_glo_n.htm#non-nil"><I>non-nil</I></A> symbol or is not present. When the short form is used, <I>name</I> is defined as a type of method combination that produces a Lisp form <TT>(</TT><I>operator</I><TT> </TT><I>method-call</I><TT> </TT><I>method-call</I><TT> ...)</TT>. The <I>operator</I> is a <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A> that can be the <A REL=DEFINITION HREF="26_glo_n.htm#name"><I>name</I></A> of a <A REL=DEFINITION HREF="26_glo_f.htm#function"><I>function</I></A>, <A REL=DEFINITION HREF="26_glo_m.htm#macro"><I>macro</I></A>, or <A REL=DEFINITION HREF="26_glo_s.htm#special_operator"><I>special operator</I></A>. The <I>operator</I> can be supplied by a keyword option; it defaults to <I>name</I>. <P>
|
||
|
Keyword options for the short form are the following: <P>
|
||
|
<P><UL><P>
|
||
|
<LI> The <TT>:documentation</TT> option is used to document the method-combination type; see description of long form below. <P>
|
||
|
<LI> The <TT>:identity-with-one-argument</TT> option enables an optimization when its value is <A REL=DEFINITION HREF="26_glo_t.htm#true"><I>true</I></A> (the default is <A REL=DEFINITION HREF="26_glo_f.htm#false"><I>false</I></A>). If there is exactly one applicable method and it is a primary method, that method serves as the effective method and <I>operator</I> is not called. This optimization avoids the need to create a new effective method and avoids the overhead of a <A REL=DEFINITION HREF="26_glo_f.htm#function"><I>function</I></A> call. This option is designed to be used with operators such as <A REL=DEFINITION HREF="s_progn.htm#progn"><B>progn</B></A>, <A REL=DEFINITION HREF="m_and.htm#and"><B>and</B></A>, <A REL=DEFINITION HREF="f_pl.htm#PL"><B>+</B></A>, and <A REL=DEFINITION HREF="f_max_m.htm#max"><B>max</B></A>. <P>
|
||
|
<LI> The <TT>:operator</TT> option specifies the <A REL=DEFINITION HREF="26_glo_n.htm#name"><I>name</I></A> of the operator. The <I>operator</I> argument is a <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A> that can be the <A REL=DEFINITION HREF="26_glo_n.htm#name"><I>name</I></A> of a <A REL=DEFINITION HREF="26_glo_f.htm#function"><I>function</I></A>, <A REL=DEFINITION HREF="26_glo_m.htm#macro"><I>macro</I></A>, or <A REL=DEFINITION HREF="26_glo_s.htm#special_form"><I>special form</I></A>. <P>
|
||
|
<P></UL><P>
|
||
|
These types of method combination require exactly one <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifier</I></A> per method. An error is signaled if there are applicable methods with no <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifiers</I></A> or with <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifiers</I></A> that are not supported by the method combination type. <P>
|
||
|
A method combination procedure defined in this way recognizes two roles for methods. A method whose one <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifier</I></A> is the symbol naming this type of method combination is defined to be a primary method. At least one primary method must be applicable or an error is signaled. A method with <TT>:around</TT> as its one <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifier</I></A> is an auxiliary method that behaves the same as an <A REL=DEFINITION HREF="26_glo_a.htm#around_method"><I>around method</I></A> in standard method combination. The <A REL=DEFINITION HREF="26_glo_f.htm#function"><I>function</I></A> <A REL=DEFINITION HREF="f_call_n.htm#call-next-method"><B>call-next-method</B></A> can only be used in <A REL=DEFINITION HREF="26_glo_a.htm#around_method"><I>around methods</I></A>; it cannot be used in primary methods defined by the short form of the <A REL=DEFINITION HREF="#define-method-combination"><B>define-method-combination</B></A> macro. <P>
|
||
|
A method combination procedure defined in this way accepts an optional argument named <I>order</I>, which defaults to <TT>:most-specific-first</TT>. A value of <TT>:most-specific-last</TT> reverses the order of the primary methods without affecting the order of the auxiliary methods. <P>
|
||
|
The short form automatically includes error checking and support for <A REL=DEFINITION HREF="26_glo_a.htm#around_method"><I>around methods</I></A>. <P>
|
||
|
For a discussion of built-in method combination types, see <A REL=CHILD HREF="07_ffd.htm">Section 7.6.6.4 (Built-in Method Combination Types)</A>. <P>
|
||
|
<DT><B>Long Form</B> <P><DD>
|
||
|
The long form syntax of <A REL=DEFINITION HREF="#define-method-combination"><B>define-method-combination</B></A> is recognized when the second <A REL=DEFINITION HREF="26_glo_s.htm#subform"><I>subform</I></A> is a list. <P>
|
||
|
The <I>lambda-list</I> receives any arguments provided after the <A REL=DEFINITION HREF="26_glo_n.htm#name"><I>name</I></A> of the method combination type in the <TT>:method-combination</TT> option to <A REL=DEFINITION HREF="m_defgen.htm#defgeneric"><B>defgeneric</B></A>. <P>
|
||
|
A list of method group specifiers follows. Each specifier selects a subset of the applicable methods to play a particular role, either by matching their <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifiers</I></A> against some patterns or by testing their <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifiers</I></A> with a <I>predicate</I>. These method group specifiers define all method <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifiers</I></A> that can be used with this type of method combination. <P>
|
||
|
The <A REL=DEFINITION HREF="26_glo_c.htm#car"><I>car</I></A> of each <I>method-group-specifier</I> is a <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A> which <A REL=DEFINITION HREF="26_glo_n.htm#name"><I>names</I></A> a <A REL=DEFINITION HREF="26_glo_v.htm#variable"><I>variable</I></A>. During the execution of the <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>forms</I></A> in the body of <A REL=DEFINITION HREF="#define-method-combination"><B>define-method-combination</B></A>, this <A REL=DEFINITION HREF="26_glo_v.htm#variable"><I>variable</I></A> is bound to a list of the <A REL=DEFINITION HREF="26_glo_m.htm#method"><I>methods</I></A> in the method group. The <A REL=DEFINITION HREF="26_glo_m.htm#method"><I>methods</I></A> in this list occur in the order specified by the <TT>:order</TT> option. <P>
|
||
|
If <I>qualifier-pattern</I> is a <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A> it must be <A REL=DEFINITION HREF="a_st.htm#ST"><B>*</B></A>. A method matches a <I>qualifier-pattern</I> if the method's list of <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifiers</I></A> is <A REL=DEFINITION HREF="f_equal.htm#equal"><B>equal</B></A> to the <I>qualifier-pattern</I> (except that the symbol <A REL=DEFINITION HREF="a_st.htm#ST"><B>*</B></A> in a <I>qualifier-pattern</I> matches anything). Thus a <I>qualifier-pattern</I> can be one of the following: the <A REL=DEFINITION HREF="26_glo_e.htm#empty_list"><I>empty list</I></A>, which matches <A REL=DEFINITION HREF="26_glo_u.htm#unqualified_method"><I>unqualified methods</I></A>; the symbol <A REL=DEFINITION HREF="a_st.htm#ST"><B>*</B></A>, which matches all methods; a true list, which matches methods with the same number of <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifiers</I></A> as the length of the list when each <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifier</I></A> matches the corresponding list element; or a dotted list that ends in the symbol <A REL=DEFINITION HREF="a_st.htm#ST"><B>*</B></A> (the <A REL=DEFINITION HREF="a_st.htm#ST"><B>*</B></A> matches any number of additional <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifiers</I></A>). <P>
|
||
|
Each applicable method is tested against the <I>qualifier-patterns</I> and <I>predicates</I> in left-to-right order. As soon as a <I>qualifier-pattern</I> matches or a <I>predicate</I> returns true, the method becomes a member of the corresponding method group and no further tests are made. Thus if a method could be a member of more than one method group, it joins only the first such group. If a method group has more than one <I>qualifier-pattern</I>, a method need only satisfy one of the <I>qualifier-patterns</I> to be a member of the group. <P>
|
||
|
The <A REL=DEFINITION HREF="26_glo_n.htm#name"><I>name</I></A> of a <I>predicate</I> function can appear instead of <I>qualifier-patterns</I> in a method group specifier. The <I>predicate</I> is called for each method that has not been assigned to an earlier method group; it is called with one argument, the method's <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifier</I></A> <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>list</I></A>. The <I>predicate</I> should return true if the method is to be a member of the method group. A <I>predicate</I> can be distinguished from a <I>qualifier-pattern</I> because it is a <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A> other than <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A> or <A REL=DEFINITION HREF="a_st.htm#ST"><B>*</B></A>. <P>
|
||
|
If there is an applicable method that does not fall into any method group, the <A REL=DEFINITION HREF="26_glo_f.htm#function"><I>function</I></A> <A REL=DEFINITION HREF="f_invali.htm#invalid-method-error"><B>invalid-method-error</B></A> is called. <P>
|
||
|
Method group specifiers can have keyword options following the <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifier</I></A> patterns or predicate. Keyword options can be distinguished from additional <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifier</I></A> patterns because they are neither lists nor the symbol <A REL=DEFINITION HREF="a_st.htm#ST"><B>*</B></A>. The keyword options are as follows: <P>
|
||
|
<P><UL><P>
|
||
|
<LI> The <TT>:description</TT> option is used to provide a description of the role of methods in the method group. Programming environment tools use <TT>(apply #'format stream </TT><I>format-control</I><TT> (method-qualifiers </TT><I>method</I><TT>))</TT> to print this description, which is expected to be concise. This keyword option allows the description of a method <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifier</I></A> to be defined in the same module that defines the meaning of the method <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifier</I></A>. In most cases, <I>format-control</I> will not contain any <A REL=DEFINITION HREF="f_format.htm#format"><B>format</B></A> directives, but they are available for generality. If <TT>:description</TT> is not supplied, a default description is generated based on the variable name and the <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifier</I></A> patterns and on whether this method group includes the <A REL=DEFINITION HREF="26_glo_u.htm#unqualified_method"><I>unqualified methods</I></A>. <P>
|
||
|
<LI> The <TT>:order</TT> option specifies the order of methods. The <I>order</I> argument is a <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> that evaluates to <TT>:most-specific-first</TT> or <TT>:most-specific-last</TT>. If it evaluates to any other value, an error is signaled. If <TT>:order</TT> is not supplied, it defaults to <TT>:most-specific-first</TT>. <P>
|
||
|
<LI> The <TT>:required</TT> option specifies whether at least one method in this method group is required. If its value is <A REL=DEFINITION HREF="26_glo_t.htm#true"><I>true</I></A> and the method group is empty (that is, no applicable methods match the <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifier</I></A> patterns or satisfy the predicate), an error is signaled. If <TT>:required</TT> is not supplied, it defaults to <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A>. <P>
|
||
|
<P></UL><P>
|
||
|
The use of method group specifiers provides a convenient syntax to select methods, to divide them among the possible roles, and to perform the necessary error checking. It is possible to perform further filtering of methods in the body <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>forms</I></A> by using normal list-processing operations and the functions <A REL=DEFINITION HREF="f_method.htm#method-qualifiers"><B>method-qualifiers</B></A> and <A REL=DEFINITION HREF="f_invali.htm#invalid-method-error"><B>invalid-method-error</B></A>. It is permissible to use <A REL=DEFINITION HREF="s_setq.htm#setq"><B>setq</B></A> on the variables named in the method group specifiers and to bind additional variables. It is also possible to bypass the method group specifier mechanism and do everything in the body <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>forms</I></A>. This is accomplished by writing a single method group with <A REL=DEFINITION HREF="a_st.htm#ST"><B>*</B></A> as its only <I>qualifier-pattern</I>; the variable is then bound to a <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>list</I></A> of all of the <A REL=DEFINITION HREF="26_glo_a.htm#applicable_method"><I>applicable methods</I></A>, in most-specific-first order. <P>
|
||
|
The body <I>forms</I> compute and return the <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> that specifies how the methods are combined, that is, the effective method. The effective method is evaluated in the <A REL=DEFINITION HREF="26_glo_n.htm#null_lexical_environment"><I>null lexical environment</I></A> augmented with a local macro definition for <A REL=DEFINITION HREF="m_call_m.htm#call-method"><B>call-method</B></A> and with bindings named by symbols not <A REL=DEFINITION HREF="26_glo_a.htm#accessible"><I>accessible</I></A> from the <TT>COMMON-LISP-USER</TT> package. Given a method object in one of the <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>lists</I></A> produced by the method group specifiers and a <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>list</I></A> of next methods, <A REL=DEFINITION HREF="m_call_m.htm#call-method"><B>call-method</B></A> will invoke the method such that <A REL=DEFINITION HREF="f_call_n.htm#call-next-method"><B>call-next-method</B></A> has available the next methods. <P>
|
||
|
When an effective method has no effect other than to call a single method, some implementations employ an optimization that uses the single method directly as the effective method, thus avoiding the need to create a new effective method. This optimization is active when the effective method form consists entirely of an invocation of the <A REL=DEFINITION HREF="m_call_m.htm#call-method"><B>call-method</B></A> macro whose first <A REL=DEFINITION HREF="26_glo_s.htm#subform"><I>subform</I></A> is a method object and whose second <A REL=DEFINITION HREF="26_glo_s.htm#subform"><I>subform</I></A> is <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A> or unsupplied. Each <A REL=DEFINITION HREF="#define-method-combination"><B>define-method-combination</B></A> body is responsible for stripping off redundant invocations of <A REL=DEFINITION HREF="s_progn.htm#progn"><B>progn</B></A>, <A REL=DEFINITION HREF="m_and.htm#and"><B>and</B></A>, <A REL=DEFINITION HREF="s_mult_1.htm#multiple-value-prog1"><B>multiple-value-prog1</B></A>, and the like, if this optimization is desired. <P>
|
||
|
The list <TT>(:arguments . </TT><I>lambda-list</I><TT>)</TT> can appear before any declarations or <A REL=DEFINITION HREF="26_glo_d.htm#documentation_string"><I>documentation string</I></A>. This form is useful when the method combination type performs some specific behavior as part of the combined method and that behavior needs access to the arguments to the <A REL=DEFINITION HREF="26_glo_g.htm#generic_function"><I>generic function</I></A>. Each parameter variable defined by <I>lambda-list</I> is bound to a <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> that can be inserted into the effective method. When this <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> is evaluated during execution of the effective method, its value is the corresponding argument to the <A REL=DEFINITION HREF="26_glo_g.htm#generic_function"><I>generic function</I></A>; the consequences of using such a <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> as the <I>place</I> in a <A REL=DEFINITION HREF="m_setf_.htm#setf"><B>setf</B></A> <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> are undefined. Argument correspondence is computed by dividing the <TT>:arguments</TT> <I>lambda-list</I> and the <A REL=DEFINITION HREF="26_glo_g.htm#generic_function"><I>generic function</I></A> <I>lambda-list</I> into three sections: the <A REL=DEFINITION HREF="26_glo_r.htm#required_parameter"><I>required parameters</I></A>, the <A REL=DEFINITION HREF="26_glo_o.htm#optional_parameter"><I>optional parameters</I></A>, and the <A REL=DEFINITION HREF="26_glo_k.htm#keyword"><I>keyword</I></A> and <A REL=DEFINITION HREF="26_glo_r.htm#rest_parameter"><I>rest parameters</I></A>. The <A REL=DEFINITION HREF="26_glo_a.htm#argument"><I>arguments</I></A> supplied to the <A REL=DEFINITION HREF="26_glo_g.htm#generic_function"><I>generic function</I></A> for a particular <A REL=DEFINITION HREF="26_glo_c.htm#call"><I>call</I></A> are also divided into three sections; the required <A REL=DEFINITION HREF="26_glo_a.htm#argument"><I>arguments</I></A> section contains as many <A REL=DEFINITION HREF="26_glo_a.htm#argument"><I>arguments</I></A> as the <A REL=DEFINITION HREF="26_glo_g.htm#generic_function"><I>generic function</I></A> has <A REL=DEFINITION HREF="26_glo_r.htm#required_parameter"><I>required parameters</I></A>, the optional <A REL=DEFINITION HREF="26_glo_a.htm#argument"><I>arguments</I></A> section contains as many arguments as the <A REL=DEFINITION HREF="26_glo_g.htm#generic_function"><I>generic function</I></A> has <A REL=DEFINITION HREF="26_glo_o.htm#optional_parameter"><I>optional parameters</I></A>, and the keyword/rest <A REL=DEFINITION HREF="26_glo_a.htm#argument"><I>arguments</I></A> section contains the remaining arguments. Each <A REL=DEFINITION HREF="26_glo_p.htm#parameter"><I>parameter</I></A> in the required and optional sections of the <TT>:arguments</TT> <I>lambda-list</I> accesses the argument at the same position in the corresponding section of the <A REL=DEFINITION HREF="26_glo_a.htm#argument"><I>arguments</I></A>. If the section of the <TT>:arguments</TT> <I>lambda-list</I> is shorter, extra <A REL=DEFINITION HREF="26_glo_a.htm#argument"><I>arguments</I></A> are ignored. If the section of the <TT>:arguments</TT> <I>lambda-list</I> is longer, excess <A REL=DEFINITION HREF="26_glo_r.htm#required_parameter"><I>required parameters</I></A> are bound to forms that evaluate to <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A> and excess <A REL=DEFINITION HREF="26_glo_o.htm#optional_parameter"><I>optional parameters</I></A> are <A REL=DEFINITION HREF="26_glo_b.htm#bound"><I>bound</I></A> to their initforms. The <A REL=DEFINITION HREF="26_glo_k.htm#keyword_parameter"><I>keyword parameters</I></A> and <A REL=DEFINITION HREF="26_glo_r.htm#rest_parameter"><I>rest parameters</I></A> in the <TT>:arguments</TT> <I>lambda-list</I> access the keyword/rest section of the <A REL=DEFINITION HREF="26_glo_a.htm#argument"><I>arguments</I></A>. If the <TT>:arguments</TT> <I>lambda-list</I> contains <TT>&key</TT>, it behaves as if it
|
||
|
In addition, <TT>&whole</TT> <I>var</I> can be placed first in the <TT>:arguments</TT> <I>lambda-list</I>. It causes <I>var</I> to be <A REL=DEFINITION HREF="26_glo_b.htm#bound"><I>bound</I></A> to a <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> that <A REL=DEFINITION HREF="26_glo_e.htm#evaluate"><I>evaluates</I></A> to a <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>list</I></A> of all of the <A REL=DEFINITION HREF="26_glo_a.htm#argument"><I>arguments</I></A> supplied to the <A REL=DEFINITION HREF="26_glo_g.htm#generic_function"><I>generic function</I></A>. This is different from <TT>&rest</TT> because it accesses all of the arguments, not just the keyword/rest <A REL=DEFINITION HREF="26_glo_a.htm#argument"><I>arguments</I></A>. <P>
|
||
|
<P>
|
||
|
Erroneous conditions detected by the body should be reported with <A REL=DEFINITION HREF="f_meth_1.htm#method-combination-error"><B>method-combination-error</B></A> or <A REL=DEFINITION HREF="f_invali.htm#invalid-method-error"><B>invalid-method-error</B></A>; these <A REL=DEFINITION HREF="26_glo_f.htm#function"><I>functions</I></A> add any necessary contextual information to the error message and will signal the appropriate error. <P>
|
||
|
The body <I>forms</I> are evaluated inside of the <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>bindings</I></A> created by the <A REL=DEFINITION HREF="26_glo_l.htm#lambda_list"><I>lambda list</I></A> and method group specifiers. Declarations at the head of the body are positioned directly inside of <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>bindings</I></A> created by the <A REL=DEFINITION HREF="26_glo_l.htm#lambda_list"><I>lambda list</I></A> and outside of the <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>bindings</I></A> of the method group variables. Thus method group variables cannot be declared in this way. <A REL=DEFINITION HREF="s_locall.htm#locally"><B>locally</B></A> may be used around the body, however. <P>
|
||
|
Within the body <I>forms</I>, <I>generic-function-symbol</I> is bound to the <A REL=DEFINITION HREF="26_glo_g.htm#generic_function"><I>generic function</I></A> <A REL=DEFINITION HREF="26_glo_o.htm#object"><I>object</I></A>. <P>
|
||
|
<I>Documentation</I> is attached as a <A REL=DEFINITION HREF="26_glo_d.htm#documentation_string"><I>documentation string</I></A> to <I>name</I> (as kind <B>method-combination</B>) and to the <A REL=DEFINITION HREF="26_glo_m.htm#method_combination"><I>method combination</I></A> <A REL=DEFINITION HREF="26_glo_o.htm#object"><I>object</I></A>. <P>
|
||
|
Note that two methods with identical specializers, but with different <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifiers</I></A>, are not ordered by the algorithm described in Step 2 of the method selection and combination process described in <A REL=CHILD HREF="07_ff.htm">Section 7.6.6 (Method Selection and Combination)</A>. Normally the two methods play different roles in the effective method because they have different <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifiers</I></A>, and no matter how they are ordered in the result of Step 2, the effective method is the same. If the two methods play the same role and their order matters, an error is signaled. This happens as part of the <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifier</I></A> pattern matching in <A REL=DEFINITION HREF="#define-method-combination"><B>define-method-combination</B></A>. <P>
|
||
|
<P></DL><P>
|
||
|
If a <A REL=DEFINITION HREF="#define-method-combination"><B>define-method-combination</B></A> <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> appears as a <A REL=DEFINITION HREF="26_glo_t.htm#top_level_form"><I>top level form</I></A>, the <A REL=DEFINITION HREF="26_glo_c.htm#compiler"><I>compiler</I></A> must make the <A REL=DEFINITION HREF="26_glo_m.htm#method_combination"><I>method combination</I></A> <A REL=DEFINITION HREF="26_glo_n.htm#name"><I>name</I></A> be recognized as a valid <A REL=DEFINITION HREF="26_glo_m.htm#method_combination"><I>method combination</I></A> <A REL=DEFINITION HREF="26_glo_n.htm#name"><I>name</I></A> in subsequent <A REL=DEFINITION HREF="m_defgen.htm#defgeneric"><B>defgeneric</B></A> <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>forms</I></A>. However, the <A REL=DEFINITION HREF="26_glo_m.htm#method_combination"><I>method combination</I></A> is executed no earlier than when the <A REL=DEFINITION HREF="#define-method-combination"><B>define-method-combination</B></A> <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> is executed, and possibly as late as the time that <A REL=DEFINITION HREF="26_glo_g.htm#generic_function"><I>generic functions</I></A> that use the <A REL=DEFINITION HREF="26_glo_m.htm#method_combination"><I>method combination</I></A> are executed. <P>
|
||
|
<P><B>Examples:</B><P>
|
||
|
<P>
|
||
|
Most examples of the long form of <A REL=DEFINITION HREF="#define-method-combination"><B>define-method-combination</B></A> also illustrate the use of the related <A REL=DEFINITION HREF="26_glo_f.htm#function"><I>functions</I></A> that are provided as part of the declarative method combination facility. <P>
|
||
|
<PRE>
|
||
|
;;; Examples of the short form of define-method-combination
|
||
|
|
||
|
(define-method-combination and :identity-with-one-argument t)
|
||
|
|
||
|
(defmethod func and ((x class1) y) ...)
|
||
|
|
||
|
;;; The equivalent of this example in the long form is:
|
||
|
|
||
|
(define-method-combination and
|
||
|
(&optional (order :most-specific-first))
|
||
|
((around (:around))
|
||
|
(primary (and) :order order :required t))
|
||
|
(let ((form (if (rest primary)
|
||
|
`(and ,@(mapcar #'(lambda (method)
|
||
|
`(call-method ,method))
|
||
|
primary))
|
||
|
`(call-method ,(first primary)))))
|
||
|
(if around
|
||
|
`(call-method ,(first around)
|
||
|
(,@(rest around)
|
||
|
(make-method ,form)))
|
||
|
form)))
|
||
|
|
||
|
;;; Examples of the long form of define-method-combination
|
||
|
|
||
|
;The default method-combination technique
|
||
|
(define-method-combination standard ()
|
||
|
((around (:around))
|
||
|
(before (:before))
|
||
|
(primary () :required t)
|
||
|
(after (:after)))
|
||
|
(flet ((call-methods (methods)
|
||
|
(mapcar #'(lambda (method)
|
||
|
`(call-method ,method))
|
||
|
methods)))
|
||
|
(let ((form (if (or before after (rest primary))
|
||
|
`(multiple-value-prog1
|
||
|
(progn ,@(call-methods before)
|
||
|
(call-method ,(first primary)
|
||
|
,(rest primary)))
|
||
|
,@(call-methods (reverse after)))
|
||
|
`(call-method ,(first primary)))))
|
||
|
(if around
|
||
|
`(call-method ,(first around)
|
||
|
(,@(rest around)
|
||
|
(make-method ,form)))
|
||
|
form))))
|
||
|
|
||
|
;A simple way to try several methods until one returns non-nil
|
||
|
(define-method-combination or ()
|
||
|
((methods (or)))
|
||
|
`(or ,@(mapcar #'(lambda (method)
|
||
|
`(call-method ,method))
|
||
|
methods)))
|
||
|
|
||
|
;A more complete version of the preceding
|
||
|
(define-method-combination or
|
||
|
(&optional (order ':most-specific-first))
|
||
|
((around (:around))
|
||
|
(primary (or)))
|
||
|
;; Process the order argument
|
||
|
(case order
|
||
|
(:most-specific-first)
|
||
|
(:most-specific-last (setq primary (reverse primary)))
|
||
|
(otherwise (method-combination-error "~S is an invalid order.~@
|
||
|
:most-specific-first and :most-specific-last are the possible values."
|
||
|
order)))
|
||
|
;; Must have a primary method
|
||
|
(unless primary
|
||
|
(method-combination-error "A primary method is required."))
|
||
|
;; Construct the form that calls the primary methods
|
||
|
(let ((form (if (rest primary)
|
||
|
`(or ,@(mapcar #'(lambda (method)
|
||
|
`(call-method ,method))
|
||
|
primary))
|
||
|
`(call-method ,(first primary)))))
|
||
|
;; Wrap the around methods around that form
|
||
|
(if around
|
||
|
`(call-method ,(first around)
|
||
|
(,@(rest around)
|
||
|
(make-method ,form)))
|
||
|
form)))
|
||
|
|
||
|
;The same thing, using the :order and :required keyword options
|
||
|
(define-method-combination or
|
||
|
(&optional (order ':most-specific-first))
|
||
|
((around (:around))
|
||
|
(primary (or) :order order :required t))
|
||
|
(let ((form (if (rest primary)
|
||
|
`(or ,@(mapcar #'(lambda (method)
|
||
|
`(call-method ,method))
|
||
|
primary))
|
||
|
`(call-method ,(first primary)))))
|
||
|
(if around
|
||
|
`(call-method ,(first around)
|
||
|
(,@(rest around)
|
||
|
(make-method ,form)))
|
||
|
form)))
|
||
|
|
||
|
;This short-form call is behaviorally identical to the preceding
|
||
|
(define-method-combination or :identity-with-one-argument t)
|
||
|
|
||
|
;Order methods by positive integer qualifiers
|
||
|
;:around methods are disallowed to keep the example small
|
||
|
(define-method-combination example-method-combination ()
|
||
|
((methods positive-integer-qualifier-p))
|
||
|
`(progn ,@(mapcar #'(lambda (method)
|
||
|
`(call-method ,method))
|
||
|
(stable-sort methods #'<
|
||
|
:key #'(lambda (method)
|
||
|
(first (method-qualifiers method)))))))
|
||
|
|
||
|
(defun positive-integer-qualifier-p (method-qualifiers)
|
||
|
(and (= (length method-qualifiers) 1)
|
||
|
(typep (first method-qualifiers) '(integer 0 *))))
|
||
|
|
||
|
;;; Example of the use of :arguments
|
||
|
(define-method-combination progn-with-lock ()
|
||
|
((methods ()))
|
||
|
(:arguments object)
|
||
|
`(unwind-protect
|
||
|
(progn (lock (object-lock ,object))
|
||
|
,@(mapcar #'(lambda (method)
|
||
|
`(call-method ,method))
|
||
|
methods))
|
||
|
(unlock (object-lock ,object))))
|
||
|
|
||
|
</PRE>
|
||
|
</TT> <P>
|
||
|
<P><B>Affected By:</B> None.
|
||
|
<P>
|
||
|
<P><B>Side Effects:</B><P>
|
||
|
<P>
|
||
|
The <A REL=DEFINITION HREF="26_glo_c.htm#compiler"><I>compiler</I></A> is not required to perform any compile-time side-effects. <P>
|
||
|
<P><B>Exceptional Situations:</B><P>
|
||
|
<P>
|
||
|
Method combination types defined with the short form require exactly one <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifier</I></A> per method. An error of <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> <A REL=DEFINITION HREF="e_error.htm#error"><B>error</B></A> is signaled if there are applicable methods with no <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifiers</I></A> or with <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifiers</I></A> that are not supported by the method combination type. At least one primary method must be applicable or an error of <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> <A REL=DEFINITION HREF="e_error.htm#error"><B>error</B></A> is signaled. <P>
|
||
|
If an applicable method does not fall into any method group, the system signals an error of <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> <A REL=DEFINITION HREF="e_error.htm#error"><B>error</B></A> indicating that the method is invalid for the kind of method combination in use. <P>
|
||
|
If the value of the <TT>:required</TT> option is <A REL=DEFINITION HREF="26_glo_t.htm#true"><I>true</I></A> and the method group is empty (that is, no applicable methods match the <A REL=DEFINITION HREF="26_glo_q.htm#qualifier"><I>qualifier</I></A> patterns or satisfy the predicate), an error of <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> <A REL=DEFINITION HREF="e_error.htm#error"><B>error</B></A> is signaled. <P>
|
||
|
If the <TT>:order</TT> option evaluates to a value other than <TT>:most-specific-first</TT> or <TT>:most-specific-last</TT>, an error of <A REL=DEFINITION HREF="26_glo_t.htm#type"><I>type</I></A> <A REL=DEFINITION HREF="e_error.htm#error"><B>error</B></A> is signaled. <P>
|
||
|
<P><B>See Also:</B><P>
|
||
|
<P>
|
||
|
<A REL=DEFINITION HREF="m_call_m.htm#call-method"><B>call-method</B></A>, <A REL=DEFINITION HREF="f_call_n.htm#call-next-method"><B>call-next-method</B></A>, <A REL=DEFINITION HREF="f_docume.htm#documentation"><B>documentation</B></A>, <A REL=DEFINITION HREF="f_method.htm#method-qualifiers"><B>method-qualifiers</B></A>, <A REL=DEFINITION HREF="f_meth_1.htm#method-combination-error"><B>method-combination-error</B></A>, <A REL=DEFINITION HREF="f_invali.htm#invalid-method-error"><B>invalid-method-error</B></A>, <A REL=DEFINITION HREF="m_defgen.htm#defgeneric"><B>defgeneric</B></A>, <A REL=CHILD HREF="07_ff.htm">Section 7.6.6 (Method Selection and Combination)</A>, <A REL=CHILD HREF="07_ffd.htm">Section 7.6.6.4 (Built-in Method Combination Types)</A>, <A REL=CHILD HREF="03_dk.htm">Section 3.4.11 (Syntactic Interaction of Documentation Strings and Declarations)</A> <P>
|
||
|
<P><B>Notes:</B><P>
|
||
|
<P>
|
||
|
The <TT>:method-combination</TT> option of <A REL=DEFINITION HREF="m_defgen.htm#defgeneric"><B>defgeneric</B></A> is used to specify that a <A REL=DEFINITION HREF="26_glo_g.htm#generic_function"><I>generic function</I></A> should use a particular method combination type. The first argument to the <TT>:method-combination</TT> option is the <A REL=DEFINITION HREF="26_glo_n.htm#name"><I>name</I></A> of a method combination type and the remaining arguments are options for that type. <P>
|
||
|
<P>
|
||
|
<P><HR>The following <A REL=META HREF="../Front/X3J13Iss.htm">X3J13 cleanup issues</A>, <I>not part of the specification</I>, apply to this section:<P><UL><LI> <A REL=CHILD HREF="../Issues/iss059.htm">COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS:CLARIFY</A><LI> <A REL=CHILD HREF="../Issues/iss103.htm">DEFINE-METHOD-COMBINATION-BEHAVIOR:CLARIFY</A><LI> <A REL=CHILD HREF="../Issues/iss135.htm">DOCUMENTATION-FUNCTION-BUGS:FIX</A><LI> <A REL=CHILD HREF="../Issues/iss242.htm">METHOD-COMBINATION-ARGUMENTS:CLARIFY</A><LI> <A REL=CHILD HREF="../Issues/iss097.htm">DECLS-AND-DOC</A><P></UL><HR>
|
||
|
|
||
|
<A REL=NAVIGATOR HREF="../Front/StartPts.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Starting Points]" SRC="../Graphics/StartPts.gif" ALIGN=Bottom></A><A REL=TOC HREF="../Front/Contents.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Contents]" SRC="../Graphics/Contents.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Master.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Index]" SRC="../Graphics/Index.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Symbol.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Symbols]" SRC="../Graphics/Symbols.gif" ALIGN=Bottom></A><A REL=GLOSSARY HREF="../Body/26_a.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Glossary]" SRC="../Graphics/Glossary.gif" ALIGN=Bottom></A><A HREF="../Front/X3J13Iss.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Issues]" SRC="../Graphics/Issues.gif" ALIGN=Bottom></A><BR>
|
||
|
|
||
|
<A REL=COPYRIGHT HREF="../Front/Help.htm#Legal"><I>Copyright 1996-2005, LispWorks Ltd. All rights reserved.</I></A><P>
|
||
|
</BODY>
|
||
|
</HTML>
|