Rustのパターンマッチング(match式)の基本と応用

先生

Rustのmatch式をマスターして、コードの安全性を高め、複雑なデータ構造をスマートに処理しよう!

Rustのパターンマッチング(match式)とは?基本を徹底解説

Rustにおけるパターンマッチングは、match式を使用して、ある値が複数のパターンに合致するかどうかを調べ、合致したパターンに対応する処理を実行する強力な機能です。これは、CやJavaのswitch文よりもはるかに柔軟で表現力豊かです。データの構造に基づいて処理を分岐させることができ、コードの可読性と安全性を向上させます。

パターンマッチングは、列挙型(enum)、構造体、タプルなど、様々なデータ型に対して使用できます。これにより、複雑なデータ構造を簡潔かつ安全に扱うことが可能になります。

Rustのコンパイラは、match式がすべての可能なパターンを網羅しているかどうかをチェックします。もし網羅されていない場合、コンパイルエラーが発生し、未処理のケースを回避できます。これにより、実行時エラーのリスクを低減し、コードの信頼性を高めることができます。

match式の基本的な使い方

match式は、キーワードmatchで始まり、マッチさせる値、そして複数のパターン => 式という形式の腕(アーム)が続きます。それぞれの腕は、パターンとそれに対応する処理を定義します。

最も基本的な例として、数値のマッチングを見てみましょう。


rust
fn main() {
    let number = 3;

    match number {
        1 => println!("One!"),
        2 => println!("Two!"),
        3 => println!("Three!"),
        _ => println!("Something else!"), // デフォルトケース
    }
}

上記の例では、numberの値が1, 2, 3のいずれかに合致するかどうかを調べ、合致した場合は対応するメッセージを出力します。_はワイルドカードパターンであり、どの値にも合致します。これは、他のどのパターンにも合致しない場合のデフォルトケースとして機能します。

パターンマッチングは値を返すこともできます。


rust
fn main() {
    let number = 3;

    let text = match number {
        1 => "One",
        2 => "Two",
        3 => "Three",
        _ => "Something else",
    };

    println!("{}", text);
}

match式の応用:列挙型(Enum)との連携

列挙型(Enum)は、特定の種類の値を表現するために使用されます。match式は、列挙型のバリアントを処理する際に非常に役立ちます。


rust
enum Color {
    Red,
    Green,
    Blue,
}

fn main() {
    let color = Color::Green;

    match color {
        Color::Red => println!("It's Red!"),
        Color::Green => println!("It's Green!"),
        Color::Blue => println!("It's Blue!"),
    }
}

上記の例では、Color列挙型のバリアントに応じて異なるメッセージを出力しています。

列挙型がデータを持つ場合、match式でそのデータを取り出すことも可能です。


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

fn main() {
    let message = Message::Move { x: 10, y: 20 };

    match message {
        Message::Quit => println!("Quit"),
        Message::Move { x, y } => println!("Move to x: {}, y: {}", x, y),
        Message::Write(text) => println!("Write: {}", text),
    }
}

Message::Move { x, y }のように、構造体のフィールドを直接取り出すことができます。これにより、複雑なデータ構造を簡単に処理できます。

Option<T>型との組み合わせ

Option<T>型は、値が存在する場合(Some(T))と存在しない場合(None)を表現するために使用されます。match式は、Option<T>型を安全に処理するための標準的な方法です。


rust
fn main() {
    let some_number: Option<i32> = Some(5);
    let absent_number: Option<i32> = None;

    match some_number {
        Some(number) => println!("Some: {}", number),
        None => println!("None"),
    }

    match absent_number {
        Some(number) => println!("Some: {}", number),
        None => println!("None"),
    }
}

上記の例では、Some(number)パターンで値を取り出し、Noneパターンで値が存在しない場合の処理を行っています。Option<T>型とmatch式を組み合わせることで、null参照エラーを回避し、安全なコードを作成できます。

参考リンク

まとめ

Rustのパターンマッチング(match式)は、値の構造に基づいて処理を分岐させるための強力な機能です。列挙型、構造体、タプル、Option<T>型など、様々なデータ型に対して使用でき、コードの可読性と安全性を向上させます。match式を使いこなすことで、より安全で効率的なRustのコードを書くことができるようになります。