blog.dopana

Back

Rust基礎シリーズの第8回です。列挙型(enum)を使用すると、考えられるバリアントを列挙して1つの型を定義できます。パターンマッチングと組み合わせることで、表現力豊かな制御フローと型安全な状態表現が可能になります。

データを持つ列挙型の定義#

C言語スタイルのenumとは異なり、Rustの列挙型は各バリアント内に直接データを保持できます。

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

fn main() {
    let msg1 = Message::Write(String::from("hello"));
    let msg2 = Message::Move { x: 10, y: 20 };
}
rust

match によるパターンマッチング#

match 式は列挙型のバリアントを検査し、内部データを取り出します。Rustの match は網羅的(exhaustive)であり、考えられるすべてのバリアントを漏れなく処理する必要があります。

fn process(msg: Message) {
    match msg {
        Message::Quit => println!("終了シグナルを受信"),
        Message::Move { x, y } => println!("({x}, {y}) へ移動"),
        Message::Write(text) => println!("テキストメッセージ: {text}"),
        Message::ChangeColor(r, g, b) => println!("色を ({r}, {g}, {b}) に変更"),
    }
}
rust

Option 列挙型: nullの代替#

Rustには null が存在しません。代わりに標準ライブラリが Option<T> 列挙型を提供し、値の存在または不在を表現します。

enum Option<T> {
    Some(T),
    None,
}
rust

Option<T>T は異なる型であるため、コンパイラは T にアクセスする前に None のケースを処理することを強制します。

fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i + 1),
    }
}

let five = Some(5);
let six = plus_one(five);
let absent = plus_one(None);
rust

if let による簡潔なマッチング#

特定の1つのバリアントだけに注目し、残りを無視したい場合は if let を使用します。

let config_max = Some(8u8);

if let Some(max) = config_max {
    println!("最大値は {max} に設定されています");
}
rust

まとめ#

列挙型は複数の可能性のいずれかであるデータを表現し、match によりすべてのケースが安全に処理され、Option によってnullポインタ例外が排除されます。シリーズの次回テーマは「コレクション(Vec、String、HashMap)」です。

参考資料#