% Macro DEFMETHOD
Macro DEFMETHOD
defmethod function-name method-qualifier*
specialized-lambda-list [[declaration* | documentation]] form*
=> new-method
function-name ::= {symbol | (setf symbol)}
method-qualifier ::= non-list
specialized-lambda-list ::=
({var | (var parameter-specializer-name)}*
[&optional {var | (var [initform [supplied-p-parameter] ])}*]
[&rest var]
[&key {var | ({var | (keywordvar)} [initform [supplied-p-parameter]])}*
[&allow-other-keys] ]
[&aux {var | (var [initform] )}*])
parameter-specializer-name ::= symbol | (eql eql-specializer-form)
declaration - 宣言の式。評価はされません。
documentation - 文字列。評価はされません。
var - 変数名
eql-specializer-form - フォーム
form - フォーム
initform - フォーム
supplied-p-parameter - 変数名
new-method - 新しいメソッドオブジェクト
マクロdefmethodは、ジェネリック関数にメソッドを定義します。
もし(fboundp function-name)がnilのときは、
ジェリック関数は次のような設定で作成されます。
デフォルトの引数の優先順位オーダー(各引数は左が右より特定的)、
ジェネリック関数クラスはstandard-generic-function、
メソッドグラスはstandard-method、
そしてmethod-combinationはstandardです。
ジェネリック関数のラムダリストは、定義されるメソッド関数のラムダリストと合致します。
もしdefmethodフォームのキーワード引数があるときは、
ジェネリック関数のラムダリストに&keyがあります
(ただしキーワード引数自体はありません)。
もしfunction-nameが通常の関数か、マクロか、
特殊オペレーターの名前の場合はエラーが発生します。
もしジェネリック関数が現にfunction-nameという名前であるとき、 メソッドのラムダリストがそのジェネリック関数のラムダリストと合致します。 もしこの状態が保持できないときは、エラーが発せられます。 この文脈の合致についての定義は、7.6.4. ジェネリック関数の全てのメソッドのラムダリストの合意をご確認ください。
各method-qualifierの引数は、
メソッドを識別するためにmethod-combinationで使用されるオブジェクトです。
method-combinationタイプは、メソッドの修飾子でできることを
さらに制限するかもしれません。
standard method-combinationタイプは、
修飾子のないメソッドと、
:before, :after, :aroundいずれかのキーワードの
単体の修飾子を使用することができます。
引数specialized-lambda-listは、通常のラムダリストと似ていますが、
要求パラメーターを特化したパラメーターに置き換えることができます。
特化したパラメーターは(var parameter-specializer-name)形式のリストです。
ただ要求パラメーターだけが特定化できます。
もし、parameter-specializer-nameがシンボルのときは、クラスの名前です。
もしリストの場合は、(eql eql-specializer-form)の形式になります。
parameter-specializer-nameが(eql eql-specializer-form)形式のときは、
対応する引数がeql-specializer-formの値のオブジェクトと、
eqlで一致しなければメソッドが適用できないことを意味します。
要求パラメーターにparameter-specializer-nameがない場合は、
標準の値としてクラスtが与えられます。
さらなる詳細については、7.6.2. メソッドの紹介をご確認ください。
引数formは、メソッドのボディ部です。
メソッドのボディ部は、暗黙のblockで囲まれます。
もしfunction-nameがシンボルのとき、
blockの名前はジェネリック関数と同じ名前です。
もしfunction-nameが(setf symbol)のリスト形式の場合は、
blockの名前はsymbolです。
作成されるメソッドオブジェクトのクラスは、 メソッドを定義するジェネリック関数の メソッドクラスオプションで指定されたものです。
もしジェネリック関数が、特定化されたパラメーターと修飾子が
合致しているメソッドをすでに持っている場合は、
defmethodは既存のメソッドを定義された現在のものに置き換えます。
特定化されたパラメーターについては、 7.6.2. メソッドの紹介で説明したように特定パラメーター名から派生します。
マクロdefmethodの展開は、各特化したパラメーターを参照します
(declareの定義のignoreの定義を参照してください)。
これは、特定化するパラメーター名を
明にtとした場合も含まれます。
つまり、メソッド本体で特化したパラメーターが参照されない場合でも
コンパイラーは警告を出力しませんが、
メソッド本体で特化したパラメーターではない
パラメーターが参照されない場合は警告を発します。
このため、tを特定化したパラメーターは、
特化したパラメーターではないパラメーターと
文脈的に同一ではありません。
メソッド本体の先頭にある宣言で、 メソッドのラムダリストの変数に適用されるものは、 束縛に対応するものと同じスコープを持つ宣言として扱われます。
メソッド本体の先頭にある宣言で、
call-next-methodとnext-method-pに束縛されてる関数への適用は、
メソッドのボディ部内でのそれらの関数の参照に適用されます。
外側で行われる
call-next-methodとnext-method-pの
どのような束縛についても、
またそれらの束縛に関連付けられる宣言に対しても、
メソッドのボディ部内では隠蔽されます。
メソッド本体の先頭にある自由形式の宣言の範囲は メソッドのボディ部全体であり、 それは暗黙のローカル関数の定義も含まれます。 しかしラムダリストの変数の初期化フォームは除外されます。
defmethodは、コンパイル時にはどのような副作用も要求されていません。
特に、コンパイル時に呼び出すためのメソッドは導入されません。
実装者は、コンパイル時のエラーチェック
(関数呼び出し時の引数の個数チェックであったり、
あるいは関数名の定義を確認したりすること)のために、
ジェネリック関数についての情報を保存するか選択できます。
documentationは、メソッドオブジェクトにドキュメント文字を割り当てます。
なし。
参照されるジェネリック関数の定義
もしfunction-nameが通常の関数か、マクロか、
特殊オペレーターの名前の場合は、
型errorのエラーが発生します。
もしジェネリック関数が現にfunction-nameという名前であるとき、
メソッドのラムダリストがそのジェネリック関数のラムダリストと合致します。
もしこの状態が保持できないときは、
型errorのエラーが発生します。
defgeneric,
documentation,
7.6.2. メソッドの紹介,
7.6.4. ジェネリック関数の全てのメソッドのラムダリストの合意,
7.6.3. 特定パラメーターと修飾子の合致,
3.4.11. ドキュメント文字と宣言の文脈的な作用
なし。