汎用関数

コンピュータプログラミングにおいて、ジェネリック関数は多態性のために定義された関数です。

静的型付け言語では

静的型付け言語( C++Javaなど)において、ジェネリック関数という用語は、コンパイル時ポリモーフィズム静的ディスパッチ)、特にパラメトリックポリモーフィズムのメカニズムを指します。これらはTypeParametersで定義され、コンパイル時の型情報によって解決されることを意図した関数です。コンパイラはこれらの型を用いて適切なバージョンをインスタンス化し、関数のオーバーロードを適切に解決します。

Common Lispオブジェクトシステム

Common Lisp Object System (CLOS) [ 1 ]Dylanなどのオブジェクト指向プログラミングシステムでは、ジェネリック関数とは、同じ名前を持つすべてのメソッドから構成される実体です。一般的に、ジェネリック関数はfunctionstandard-objectの両方を継承するクラスのインスタンスです。つまり、ジェネリック関数は、関数(引数を指定して呼び出したり、引数に適用したりできる)であると同時に、通常のオブジェクトでもあります。書籍『The Art of the Metaobject Protocol』では、CLOSジェネリック関数の実装と使用法について詳細に説明しています。

Lispにおける初期のオブジェクト指向プログラミング拡張の一つにFlavorsがあります。これはSmalltalkの影響を受けた一般的なメッセージ送信パラダイムを採用していました。Flavorsによるメッセージ送信構文は次のとおりです。

(オブジェクトを送信: メッセージ)

New Flavors では、メッセージは実際の関数であり、通常の関数呼び出し構文が使用される必要があると決定されました。

メッセージオブジェクト

message はジェネリック関数となり、それ自体がオブジェクトであり関数でもあります。message の個々の実装はメソッド呼ばれます。

同じアイデアはCommonLoopsにも実装されました。[ 2 ] New FlavorsとCommonLoopsはCommon Lispオブジェクトシステムに大きな影響を与えました。

コモンリスプ

object-1とobject-2という2つのパラメータを持つジェネリック関数を定義します。ジェネリック関数の名前はcollideです。

( defgeneric衝突(オブジェクト1オブジェクト2 ))

ジェネリック関数に属するメソッドは、クラスの外部で定義されます。ここでは、ジェネリック関数collideのメソッドを定義し、このメソッドはasteroid(最初の引数object-1)とspaceship(2番目の引数object-2)というクラスに特化されています。これらの引数は、メソッド本体内で通常の変数として使用されます。クラススロットにアクセスできる特別な名前空間は存在しません。

( defmethod collide (( object-1 asteroid ) ( object-2 spaceship )) ( format t "asteroid ~a が spaceship ~a と衝突する" object-1 object-2 ))

ジェネリック関数の呼び出し:

? ( collide ( make-instance 'asteroid ) ( make-instance 'spaceship ))小惑星# <ASTEROID 4020003FD3>が宇宙船# <SPACESHIP 40200048CB>衝突します

Common Lispは、ジェネリック関数から個々のメソッドを取得することもできます。FIND-METHODは、 asteroidクラスとspaceshipクラスに特化したジェネリック関数collideからメソッドを検索します。

? ( find-method #' collide nil ( list ( find-class 'asteroid ) ( find-class 'spaceship ))) # <STANDARD-METHOD COLLIDE NIL ( ASTEROID SPACESHIP ) 4150015E43>

他の言語との比較

ジェネリック関数は、 Smalltalkでメソッドと呼ばれるものにほぼ相当しますが、Smalltalkでは、レシーバのクラスが、どのコード本体が呼び出されるかを決定する唯一の要素であるという顕著な例外があります。つまり、引数の型や値は無関係です(単一ディスパッチ)。多重ディスパッチをサポートするプログラミング言語では、ジェネリック関数が呼び出されると、メソッドのディスパッチは、特権引数だけでなく、すべての引数に基づいて行われます。New Flavorsでもジェネリック関数は提供されていましたが、単一ディスパッチのみでした。

JavaScriptにおけるジェネリック関数とは、特定の型ではなく、異なる型の値を処理できる関数です。これは、型パラメータを使用するか、処理対象の値の型を動的にチェックすることで実現されます。JavaScriptにおけるジェネリック関数の一般的な使用例の一つは、配列、文​​字列、オブジェクトなど、異なるデータ型を処理できる再利用可能な関数を作成することです。JavaScriptの動的型付けシステムは、必要に応じて値を簡単に強制型変換できるため、ジェネリック関数の作成に特に適しています。

参考文献