【Rust入門】列挙型の基本を分かりやすく解説

Rust の列挙型(enum)の基本を初心者にも分かりやすく解説します。
Rust の列挙型(enum)
列挙型(enum)とは
Rust の列挙型(enum)とは、「複数の選択肢のうち、どれか1つを表現したい」ときに使える型です。Rust には構造体という型を定義する仕組みがありますが、構造体はデータがどういった構成をしているかを表すのに対して、列挙型は選択肢のいずれか1つの値を表現するという点で違いがあります。例えば「日曜~土曜のいずれか」のような選択肢は代表的な例でしょう。これらの enum の中で定義された各選択肢を「バリアント(variant)」と呼びます。
enum は、C 言語や Java など多くのプログラミング言語にも存在していますが、Rust の列挙型が特に強力なのは、各バリアントごとにデータを持たせることができるという点です。つまり、単に名前がついた定数の集まりではなく、それぞれのバリアントが異なるデータ構造を持つことができる柔軟な型として機能します。これらは、Rust のパターンマッチングの機能と連携することで非常に強力な表現力と安全なコーディングを提供します。
この記事では、列挙型の基本的な定義の方法や代表的な列挙型の例である Option<T> 型と Result<T, E> 型について説明します。パターンマッチングと連携した活用方法については別記事でまたまとめてご紹介します。
基本的な列挙型
まずは、基本的な列挙型の定義方法を見ていきましょう。列挙型は、enum キーワードを使って定義し、ブロック内でバリアントを列挙します。列挙型名やバリアント名は、CamelCase(単語の先頭が大文字)で定義するのが慣習です。
#[allow(dead_code)]
#[derive(Debug)]
// 曜日を表す列挙型
enum WeekDay {
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
}
fn main() {
let today = WeekDay::Sunday;
println!("Today is {today:?}");
}【実行結果】 Today is Sunday
列挙型のバリアントを使用する際には「列挙型名::バリアント名」という形で使用します。上記では、today 変数に WeekDay::Sunday という日曜日を表すバリアントを束縛しています。
値を持つ列挙型
上記で使用したような使い方は、他のプログラミングでも一般的に使用できる方法です。Rust の enum では、異なる型や構造のデータを持つことができます。
例えば、あるシステムで扱うメッセージを表す Message 型を以下のように定義できます。
#[allow(dead_code)]
#[derive(Debug)]
// メッセージを表す列挙型
enum Message {
Quit,
Echo(String),
Move(i32, i32),
ChangeColor { r: u8, g: u8, b: u8, a: f32 },
}
fn main() {
// 終了を伝えるメッセージ
let quit = Message::Quit;
println!("Quit message: {quit:?}");
// 文字列を表示するメッセージ
let echo = Message::Echo(String::from("メッセージ"));
println!("Echo message: {echo:?}");
// (x, y) = (5, 10) への移動を表すメッセージ
let move_position = Message::Move(5, 10);
println!("Move message: {move_position:?}");
// 色を変更する (r:赤, g:緑, b:青, a:透明度(0.0~1.0))
let change_color = Message::ChangeColor {
r: 255,
g: 255,
b: 0,
a: 0.5,
};
println!("ChangeColor message: {change_color:?}");
}【実行結果】
Quit message: Quit
Echo message: Echo("メッセージ")
Move message: Move(5, 10)
ChangeColor message: ChangeColor { r: 255, g: 255, b: 0, a: 0.5 }上記例では、以下のような種類のバリアントを作成しています。
Quit:通常のバリアントEcho:タプル形式で単一のString型を持つバリアントMove:タプル形式で複数の型を持つバリアントChangeColor:名前付きフィールド(構造体形式)で各型を持つバリアント
このように値付きでバリアントを持たせると、状態毎により異なるメッセージを統一的に Message 型で扱うことができ、設計や保守性が向上します。
重要な列挙型(Option<T> 型と Result<T, E> 型)
Rust の列挙型で標準で用意されているものにおいてとても重要な列挙型として、Option<T> 型と Result<T, E> 型があります。これらの使い方は別途まとめてみたいと思いますが、ここでは概要を紹介します。(※ T や E は型パラメータと呼ばれ、後から使う側が具体的な型を指定できるジェネリックな仕組みです。)
値の有無を表現する Option<T> 型
Rust では、他のプログラミングにおける null のようなものはありません。Rust では、ある値が「あるかもしれないし、ないかもしれない」という状況を Option<T> 型 で表現できます。
Option<T> は、概念的には以下のような enum として定義されています。(※実際の実装が以下の通りというわけではないため注意してください。)
enum Option<T> {
Some(T), // 値が存在する (T は任意の型)
None, // 値が存在しない
}Option<T> の使用例は以下の通りです。
fn main() {
let name: Option<String> = Some(String::from("山田太郎"));
println!("{name:?}");
let empty: Option<String> = None;
println!("{empty:?}");
}【実行結果】
Some("山田太郎")
NoneOption<T> 型は、値がある場合は「Some(T)」、値がない場合は「None」として型が定義されています。上記使用例では、T の部分を String であった場合です。
C などの他の言語では、null を一旦代入しておくということが多いですが、null のままであることを忘れて後続の処理を書いてしまうと予期せぬバグにつながります。
Rust には、多くの言語にあるような null が言語仕様として存在しません。そのため、Option 型で存在しないかもしれないことを明示的に表現することで、プログラマは、値がないかもしれない場合について向き合い処理を記載する必要があります。
成功と失敗を表現する Result<T, E> 型
Option<T> 型と同様に非常に重要な型として、Result<T, E> 型があります。Rust では、他のプログラミング言語である例外という考え方がありません。その代わりに、この Result<T, E> 型のような型を使用します。この型は、関数等の戻り値として非常によく利用され「処理が成功したか、失敗したか」を表現します。
Result<T, E> は、概念的には以下のような enum として定義されています。(※実際の実装が以下の通りというわけではないため注意してください。)
enum Result<T, E> {
Ok(T), // 処理が成功 T は成功時の値の型
Err(E), // 処理が失敗 E はエラー情報を含む型
}Result<T, E> の使用例は以下の通りです。
fn main() {
let result: Result<i32, &str> = Ok(42);
println!("{result:?}");
let error: Result<i32, &str> = Err("処理に失敗しました");
println!("{error:?}");
}【実行結果】
Ok(42)
Err("処理に失敗しました")Result<T, E> 型は、成功した場合は「Ok(T)」、処理が失敗した場合は「Err(E)」として型が定義されています。上記使用例では、T が i32 なので成功したら i32 型の値が返却され、E は &str なので処理が失敗した場合には失敗メッセージが返ってくるような場合です。
こちらも Option<T> 型の場合と同じで、 という1つの型で成功と失敗を明示的に表現しています。そのため、この型の返却値を受け取った処理では、成功と失敗に向き合い、適切に処理をする必要があります。Result<T, E> 型
Rust では、上記の Option<T> 型や は、明示的に型で扱うことでコンパイラでもバグを発見しやすくなり、コードの安全性を格段に向上します。これらの型をより活用するには、Rust の「パターンマッチング」機能と組み合わせるのが非常に強力です。Result<T, E> 型
まとめ
この記事では、Rust における列挙型(enum)の基本的な使い方や、値を持つバリアントの表現方法、そして特によく使われる Option<T> 型と Result<T, E> 型について紹介しました。
列挙型は「複数の状態のうちの 1 つ」を安全かつ柔軟に表現できる強力な仕組みです。バリアントごとに異なるデータを持たせることができる点が、Rust の列挙型の大きな特徴です。
Option<T> や Result<T, E> は、値の有無や成功・失敗といった状態を明示的に型で表現でき、バグの発見をコンパイラが手助けしてくれるという大きなメリットがあります。
列挙型は、Rust におけるプログラミングで中心的なものです。ぜひ、しっかりと考え方や使い方を理解してもらいたいと思います。
上記で紹介しているソースコードについては GitHub にて公開しています。参考にしていただければと思います。







