% Macro DEFGENERIC
Macro DEFGENERIC
defgeneric
function-name gf-lambda-list [[option |
method-description*]]
=> new-generic
option ::= (:argument-precedence-order parameter-name+) |
(declare gf-declaration+) |
(:documentation gf-documentation) |
(:method-combination method-combination method-combination-argument*) |
(:generic-function-class generic-function-class) |
(:method-class method-class)
method-description ::=
(:method method-qualifier* specialized-lambda-list
[[declaration* | documentation]] form*)
function-name - 関数名
generic-function-class - nil
ではない、クラス名のシンボル
gf-declaration - optimize
の宣言指定子。他の宣言指定子は許されません。
gf-documentation - 文字列(評価はされない)
gf-lambda-list - ジェネリック関数のラムダリスト
method-class - nil
ではない、クラス名のシンボル
method-combination-argument - オブジェクト
method-combination-name - nil
ではない、method-combinationの型の名前のシンボル
method-qualifiers, specialized-lambda-list,
declarations, documentation, forms - defmethod
に従います。
new-generic - ジェネリック関数オブジェクト
parameter-name - ラムダリスト内にある要求パラメーターの名前のシンボル。
(もし:argument-precedence-order
オプションが定義されているならば、
ラムダリスト内のそれぞれの要求パラメーターは、
parameter-nameが正確にひとつ使われなければなりません)
マクロdefgeneric
は、ジェネリック関数を定義したり、
ジェネリック関数全体に関わるオプションと宣言を指定するときに使われます。
もしfunction-nameがリストなら、(setf symbol)
の形式でなければなりません。
もし(fboundp function-name)
がfalseのときは、新しいジェネリック関数が作成されます。
もし(fdefinition function-name)
がジェネリック関数のときは、
そのジェネリック関数は変更されます。
もしfunction-nameが通常の関数か、マクロか、特殊オペレーターの名前のときは、
エラーが発生します。
defgeneric
マクロは、次に示す3つのステップが実行されたかのような効果を示します。
第一に、以前defgeneric
フォームで定義されたメソッドは削除されます。
第二に、ensure-generic-function
が呼び出されます。
そして最後に、今回のdefgeneric
フォームによって定義されたメソッドが、
ジェネリック関数に追加されます。
各method-descriptionは、そのジェネリック関数上で、メソッドが宣言されます。 各メソッドのラムダリストは、gf-lambda-listオプションによって指定された ラムダリストと合致しなければなりません。 メソッドの定義が指定されておらず、 同名のジェネリック関数が存在しない場合は、 メソッドがないジェネリック関数が作成されます。
defgeneric
の引数gf-lambda-listは、
そのジェネリック関数のメソッドに対して、
ラムダリストの形を指定します。
返却されるジェネリック関数上の全てのメソッドは、
この形に合致したラムダリストを持たなければなりません。
もし、defgeneric
フォームが評価されたとき、
そのジェネリック関数にあるメソッドのラムダリストが
defgeneric
フォームに付与されたものと合致しない場合は、
エラーが発生します。
メソッドの合致に関するさらなる詳細は、7.6.4. ジェネリック関数の全てのメソッドのラムダリストの合意をご確認ください。
ジェネリック関数は、渡されたすべての引数をメソッドに渡します。
渡されるのはそれらの値のみであり、デフォルト値は供給されません。
ただし、メソッド定義にはオプション引数とキーワード引数があり、
デフォルト値とsupplied-p
パラメーターが使用できることに注意してください。
次に示すオプションが提供されます。 注意書きがあるもの以外、オプションはただひとつ与えられます。
:argument-precedence-order
は、
ジェネリック関数が呼び出だされ、特定のメソッドを選択するときに
テストを行う要求された引数の順序を指定するために使用されます。
完全かつ曖昧がないような優先順序が与えられるように、
gf-lambda-list引数内で指定されたそれぞれのrequired-arguments}は、
正確にひとつだけparameter-nameとして含まれなければなりません。
もしこのような条件に合わない場合は、エラーが発生します。declare
のオプションは、
ジェネリック関数に関する宣言を指定するときに使われます。
optimize
宣言指定子が許されます。
この宣言は、メソッドの選択の最適化がspeed
かspace
なのかを指定するものであり、
メソッドへの効果はありません。
メソッドの最適化をどのように制御するかについては、
optimize
宣言をdefmethod
かメソッドの宣言内に
直接記載する必要があります。
標準で要求される最適化の種類はspeed
とspace
だけですが、
実装によっては他の種類も認識するように、
オブジェクトシステムを拡張することもできます。
単純な実装では、メソッドの選出方法をただひとつだけ実装し、
optimize
宣言指定子を無視するというのが有効です。special
, ftype
, function
,
inline
, notinline
, declaration
の宣言は許されていません。
各実装は、declare
オプションを拡張して、
追加の宣言をサポートすることができます。
もしある実装が、サポートしていない宣言指定子に遭遇し、
その宣言が非標準の宣言の名前でproclaim
されていた場合は、
警告を発生させるべきです。declare
オプションは、複数指定されるかもしれません。
宣言指定子のリストをひとつにまとめて、
単体のdeclare
オプションとして指定したのと同じ効果が得られます。:documentation
は、ジェネリック関数のオブジェクトにドキュメント文字を、
種類function
で、funciton-nameに割り当てられます。:generic-function-class
オプションは、
ジェネリック関数が、システムの提供するデフォルトのもの
(standard-generic-function
のクラス)とは
異なるクラスを持つことを指定するために使われます。
引数class-nameは、ジェネリック関数クラスのクラス名です。
もし、function-nameが既存のジェネリック関数を示しており、
新しいジェネリック関数の:generic-function-class
の値が
古いものと互換性がある場合は、
change-class
が呼ばれてジェネリック関数のクラスが変更されます。
それ以外の場合はエラーが発生します。:method-class
オプションは、
ジェネリック関数上の全てのメソッドが、
システムの提供するデフォルトのもの(standard-method
のクラス)とは
異なるクラスを持つことを指定するために使われます。
引数class-nameは、メソッドのクラスとなりえるクラス名です。:method-combination
オプションは、
method-combinationの型の名前であるシンボルが続きます。
そのシンボルの後に続く引数があるなら、それはmethod-combinationの型に依存します。
standard
のmethod-combinationは、引数をサポートしません。
しかし、define-method-combination
の短縮形によって宣言された
method-combinationの型は全て、orderというオプション引数を受け付けます。
デフォルトの値は:most-specific-first
であり、
もしこの値が:most-specific-last
のときは、
補助メソッドの順番に影響を与えずに、プライマリメソッドの順番を逆転させます。引数method-descriptionは、ジェネリック関数に関連付けたメソッドを宣言できます。
メソッド宣言にある引数のmethod-qualifierとspecialized-lambda-listは、
defmethod
と同じです。
引数formは、メソッドのボディ部です。
メソッドのボディ部は、暗黙のblock
で囲まれます。
もしfunction-nameがシンボルのとき、
block
の名前はジェネリック関数と同じ名前です。
もしfunction-nameが(setf symbol)
のリスト形式の場合は、
block
の名前はsymbolです。
実装は、defgeneric
に別のオプションを含めるよう拡張できます。
もし自身が実装していないオプションが見られた場合は、
その実装はエラーを発生するよう要求されます。
defgeneric
は、コンパイル時にはどのような副作用も要求されていません。
特に、コンパイル時に呼び出すためのメソッドは導入されません。
実装者は、コンパイル時のエラーチェック
(関数呼び出し時の引数の個数チェックであったり、
あるいは関数名の定義を確認したりすること)のために、
ジェネリック関数についての情報を保存するか選択できます。
なし。
なし。
もしfunction-nameが通常の関数か、マクロか、特殊オペレーターの名前のときは、
型program-error
のエラーが発生します。
引数gf-lambda-listとして指定された各要求された引数は、
parameter-nameとして正確にひとつだけ含まれなければならず、
そうでないときは、型program-error
のエラーが発生します。
method-descriptionによって指定された各メソッドのラムダリストは、
gf-lambda-listオプションによって指定されたラムダリストと合致していなければならず、
そうでないときは型error
のエラーが発生します。
もし、defgeneric
フォームが評価されたとき、
そのジェネリック関数にあるメソッドのラムダリストが
defgeneric
フォームに付与されたものと合致しない場合は、
型error
のエラーが発生します。
オプションがただひとつではなかった場合は、
型program-error
のエラーが発生します。
もし、function-nameが既存のジェネリック関数を示しており、
新しいジェネリック関数の:generic-function-class
の値が
古いものと互換性がある場合は、
change-class
が呼ばれてジェネリック関数のクラスが変更されます。
それ以外の場合は型error
のエラーが発生します。
実装は、defgeneric
に別のオプションを含めるよう拡張できます。
もし自身が実装していないオプションが見られた場合は、
その実装は型program-error
のエラーを発生するよう要求されます。
defmethod
,
documentation
,
ensure-generic-function
,
generic-function
,
7.6.4. ジェネリック関数の全てのメソッドのラムダリストの合意
なし。