RustでのDaveHermanの最近の講演によると、このプロパティはC++から借用したとのことです。トピックの周りには何も見つかりませんでした。誰かが単形化の意味を説明できますか?
4 に答える
単形化とは、ジェネリック関数の特殊なバージョンを生成することを意味します。任意のペアの最初の要素を抽出する関数を作成すると、次のようになります。
fn first<A, B>(pair: (A, B)) -> A {
let (a, b) = pair;
return a;
}
次に、この関数を2回呼び出します。
first((1, 2));
first(("a", "b"));
コンパイラはfirst()
、整数のペアに特化したバージョンと文字列のペアに特化したバージョンの2つのバージョンを生成します。
この名前は、プログラミング言語の用語「ポリモーフィズム」に由来しています。これは、多くの種類のデータを処理できる1つの関数を意味します。単形化は、多形性コードから単形性コードへの変換です。
誰かがまだこれを見ているかどうかはわかりませんが、Rustのドキュメントには、このプロセスを通じてコストの抽象化を実現する方法が実際に記載されています。ジェネリックスを使用したコードのパフォーマンスから:
ジェネリック型パラメーターを使用している場合、実行時のコストがかかるかどうか疑問に思われるかもしれません。幸いなことに、Rustはジェネリックを実装しているため、ジェネリック型を使用すると、具象型を使用した場合よりもコードの実行速度が低下しません。
Rustは、コンパイル時にジェネリックスを使用しているコードの単相化を実行することでこれを実現します。モノモルフィゼーションは、コンパイル時に使用される具体的なタイプを入力することにより、ジェネリックコードを特定のコードに変換するプロセスです。
このプロセスでは、コンパイラーは、リスト10-5でジェネリック関数を作成するために使用した手順とは逆の手順を実行します。コンパイラーは、ジェネリックコードが呼び出されるすべての場所を調べ、ジェネリックコードが呼び出される具体的なタイプのコードを生成します。 。
標準ライブラリのOption列挙型を使用する例でこれがどのように機能するかを見てみましょう。
let integer = Some(5); let float = Some(5.0);
Rustがこのコードをコンパイルすると、単形化が実行されます。そのプロセス中に、コンパイラはOptionインスタンスで使用された値を読み取り、2種類のOptionを識別します。1つはi32で、もう1つはf64です。そのため、Optionの一般的な定義をOption_i32とOption_f64に拡張し、それによって一般的な定義を特定の定義に置き換えます。
単形化されたバージョンのコードは次のようになります。汎用オプションは、コンパイラーによって作成された特定の定義に置き換えられます。
// Filename: src/main.rs enum Option_i32 { Some(i32), None, } enum Option_f64 { Some(f64), None, } fn main() { let integer = Option_i32::Some(5); let float = Option_f64::Some(5.0); }
Rustはジェネリックコードを各インスタンスのタイプを指定するコードにコンパイルするため、ジェネリックを使用するためのランタイムコストはかかりません。コードを実行すると、各定義を手動で複製した場合と同じように実行されます。単形化のプロセスにより、Rustのジェネリックは実行時に非常に効率的になります。
これについてはよくわかりません。話にリンクしてもらえますか?手に負えない発言だったのかもしれません。
Hermanは、テンプレートの特殊化のような用語を作り出した可能性があります。これは、多形構造であるテンプレートから相互に関連のない(多形ではない、または「単形」)タイプ/オブジェクトを生成します。
RustBookには単形化の良い説明があります
モノモルフィゼーションは、コンパイル時に使用される具体的なタイプを入力することにより、ジェネリックコードを特定のコードに変換するプロセスです。
本の例から、変数を次のように定義した場合Some
:
let integer = Some(5); let float = Some(5.0);
Rustがこのコードをコンパイルすると、単形化が実行されます。そのプロセス中に、コンパイラは
Option<T>
インスタンスで使用された値を読み取り、2種類を識別します。1つはで、もうOption<T>
1つはです。そのため、との一般的な定義を拡張し、 それによって一般的な定義を特定の定義に置き換えます。i32
f64
Option<T>
Option_i32
Option_f64
単形化されたバージョンのコードは次のようになります。ジェネリック
Option<T>
は、コンパイラーによって作成された特定の定義に置き換えられます。ファイル名:src / main.rs
enum Option_i32 { Some(i32), None, } enum Option_f64 { Some(f64), None, } fn main() { let integer = Option_i32::Some(5); let float = Option_f64::Some(5.0); }