ジェネリクスの基本
Rust の ジェネリクス (generics) の仕組みを使うと、任意の型を扱う処理を 1 つのコードで記述することができます。
まずは、ジェネリクスを使っていないコードから見てみます。
次のサンプルコードでは、整数型 (i32
) の座標値を表現する構造体 Point
と、その浮動小数点数型 (f64
) バージョンである PointF
を定義しています。
Rust では、数値だけでも様々なプリミティブ型 (u8
, i128
, f64
, usize
, …) で区別して扱うので、このように扱う数値の種類によってコードを書き分けなければいけません。
一方の型(上記の例では PointF
構造体)だけで実装しようとすると、as
を使ったキャストがいたるところに出てくることになります。
そこでジェネリクスの出番です。
ジェネリクスの仕組みでは、構造体や関数の定義時に 型パラメーター を宣言することで、(コンパイル時に決定される)任意の型を扱えるようになります。
次のコードは、ジェネリクス版の Point
構造体です。
汎用的な型パラメーターの名前としては、T
を使うのが慣例となっています。
これで、様々な数値型の座標値を、Point
というジェネリック構造体 1 つで表現できるようになりました!
複数の型パラメーターを扱う
型パラメーターは任意の数だけカンマで並べて宣言できます。
次の Pair
構造体は、任意の型のフィールド first
と second
を持つ構造体です。
first
と second
はそれぞれ別の型の値を保持することができます。
ジェネリクス関数
関数でも型パラメーターを使うことができます。
次の swap
関数は、2 つの値を受け取り、その順番を入れ替えたタプルを返します。
ちなみに、Rust でプリミティブ型の値をスワップしたいときは、次のようにタプルの destructuring 構文を使うのが簡単です。
let mut a = 1;
let mut b = 2;
(b, a) = (a, b); // 値のスワップ