7.6.1. ジェネリック関数の紹介
ジェネリック関数は、指定された引数のクラスか、 あるいは引数の同一性に依存して動作する関数です。 ジェネリック関数オブジェクトは、メソッドの集合、 ラムダリスト、method-combination、そしてその他の情報に関連付けられます。
通常の関数のように、ジェネリック関数は引数を取り、 一連のオペレーションを実行し、そしておそらくは有効な値を返却します。 通常の関数は単一のコードの実体を持ち、関数が呼び出されたときに常に実行されます。 ジェネリック関数はコードの実体を複数の集合として持ち、 その集合の一部か全部を関数実行のときに選択します。 選ばれたコードの集合とその組み合わせは、 ジェネリック関数に渡される1つか複数の引数から、 クラスかあるいは同一性により決定します。 それはmethod-combinationによって決定が行われます。
通常の関数とジェネリック関数は、同一の構文により呼び出されます。
ジェネリック関数は本物の関数なので、 funcall
とapply
の最初の引数として使用されたり、 あるいは引数を渡したりすることができます。
ジェネリック関数の関数名の設定は、いくつかの手順のひとつとして確立します。 それはグローバル環境内において、ensure-generic-function
, defmethod
(暗にensure-generic-function
が呼ばれる), defgeneric
(これもまた暗に、ensure-generic-function
が呼ばれる) によって確立されます。 レキシカル環境において、ジェネリック関数の関数名の束縛を確立するための 標準的な方法は提供されていません。
defgeneric
フォームが評価されるとき、 (ensure-generic-function
によって)次の3つのうちの1つの手順が取られます。
もし指定した名前のジェネリック関数がもう存在している場合は、 存在しているジェネリック関数オブジェクトを修正します。 いま実行されたdefgeneric
フォームによって宣言されたメソッドは追加され、 そして以前のdefgeneric
フォームによって定義された、 存在していたジェネリック関数のどんなメソッドも削除されます。 いま実行されたdefgeneric
フォームによるメソッドの追加は、 defmethod
, defclass
, define-condition
, そしてdefstruct
によって定義されたメソッドも置き換えます。 ジェネリック関数内のその他のメソッドについては、影響は無いですし置き換えもされません。
もし指定した名前が、通常の関数、マクロ、特殊オペレーターによる名前であった場合は、 エラーが発せられます。
そうでなければ、ジェネリック関数はdefgeneric
フォーム内にある メソッド定義により宣言されたメソッドとともに作成されます。
いくつかのオペレーターは、ジェネリック関数のオプションの定義として、 使用するmethod-combinationのタイプや引数優先順位を指定することが許されています。 これらのオペレーターは、「ジェネリック関数のオプションを指定するオペレーター」と言います。 この分類の中で、標準的なオペレーターはdefgeneric
だけです。
いくつかのオペレーターは、ジェネリック関数のメソッドを定義します。 これらのオペレーターはメソッド定義オペレーターと言われます。 このオペレーターに関連付けられたフォームは、メソッド定義フォームと呼ばれます。 標準的なメソッド定義オペレーターを次の表に示します。
defgeneric
define-condition
defmethod
defstruct
defclass
表7-1 標準メソッド定義オペレーター
注意として、標準メソッド定義オペレーターのdefgeneric
だけは、 ジェネリック関数のオプションを指定することが出来ます。 defgeneric
といくつかの実装定義オペレーターは、 ジェネリック関数のオプションを指定することが可能であり、 「ジェネリック関数のオプションを指定するオペレーター」と言われます。