Rustのmatch演算の書き方【制御フロー演算子、分岐処理】

589, 2022-11-24

目次

Rustのmatch演算を使ってみる

今回はRustのmatch演算子について解説します。
Rustでは条件分岐にif, それからmatchが使えます。

matchを使うと他言語で言うところのswitch文みたいな処理が書けます。
またRustのmatchはエラーハンドリングでもよく使われる演算子なので覚えておきたいところです。

それでは解説していきます。

match演算子の構造

まずmatch演算子の構造です。
match演算子の構造は↓のようになっています。

match 条件に使う値 {
    マッチさせたい値1 => 実行する式,
    マッチさせたい値2 => 実行する式,
    _ => 実行する式,
}

条件に使う値に対してマッチさせたい値を書き、それに=>を付けて右側にマッチした場合の式を書きます。
またマッチさせたい値にどれもマッチしなかった場合は_のところが実行されます。

match演算子は文ではなく演算子なので当然、演算結果を返します。
この辺が他言語とは違うところなので注意が必要です。

基本的なmatch演算

では基本的なmatch演算について見てみます。
整数を使った場合です。

    let n: i32 = 2;

    match n {
        0 => println!("zero"),
        1 => println!("one"),
        2 => println!("two"),
        _ => println!("other"),
    };

    // two

上の場合、条件に使う値は変数nです。
変数nには整数2が入っています。
ですので2 => ...の部分にマッチして「two」と出力されます。

nの値を変えてみると他のところにマッチしてくのがわかります。

ブレースで複数行、計算する

match演算でマッチした場合に実行する式は複数書くことができます。
その場合は=>の右側をブレース({})で囲みます。

    let n: i32 = 1;

    match n {
        0 => println!("zero"),
        1 => {
            println!("one");
            println!("you are no.1!");
            println!("i'm excellent!");
        },
        _ => println!("other"),
    };

    // one
    // you are no.1!
    // i'm excellent!

match演算で条件にマッチさせて具体的な処理を書きたい場合はこのようにブレースを使うことが多いと思います。
ただしブレースの中に文や式を書きすぎるとmatch演算が長くなってしまうので注意が必要です。
ほどほどにしてリファクタリングしてください。

match演算の結果を受け取る

match演算は演算子なので結果を返すことができます。
↓のケースはマッチした場合に大きな整数を返すようにしています。

    let n: i32 = 2;

    let result = match n {
        1 => 100,
        2 => 200,
        _ => 300,
    };

    println!("result {}", result);  // result 200

変数resultには↑の場合は200が代入されます。

文字列(&str)とマッチング

match演算は文字列とマッチングさせることもできます。
&strの文字列とマッチさせてみます。

    let s: &str = "go to heaven";

    match s {
        "go to hell" => println!("this is hell..."),
        "go to heaven" => println!("this is heaven!"),
        _ => println!("other"),
    }

    // this is heaven!

Rustでは"hello"と書いた場合はこれは&strと判断されます。
ですので↑のように文字列変数に対してダブルクオーテーションで囲った文字列をべた書きすることができます。

文字列(String)とマッチング

Stringとマッチさせたい場合はas_str()を使います。

    let s = String::from("go to heaven");

    match s.as_str() {
        "go to hell" => println!("this is hell..."),
        "go to heaven" => println!("this is heaven!"),
        _ => println!("other"),
    }

    // this is heaven!

as_str()Stringから&strを取得します。
match演算の条件式にこれを指定することで分岐のマッチさせたい文字列にマッチさせることができます。

enumとのマッチング

match演算はenum定数ともマッチングさせることができます。

    enum Number {
        One,
        Two,
        Three,
    };

    let n = Number::Two;

    match n {
        Number::One => println!("one"),
        Number::Two => println!("two"),
        Number::Three => println!("three"),
    }

    // two

enumの場合は_が省略されていることに注意してください。
別に省略しなくてもいいんですが、enumに列挙されている定数を網羅的にmatch演算に書いておけば、警告などが出力されることはありません。
match演算は網羅的につまり包括的に値を処理します。
ですのでi32などを条件にした場合は_を省略すると怒られてしまいます。

Optionをmatchで処理する

Optionをmatch演算で処理することもできます。

    fn get_user_age(user_id: i32) -> Option<usize> {
        match user_id {
            0 => Some(20),
            1 => Some(30),
            _ => None,
        }
    }

    match get_user_age(1) {
        None => println!("not found"),
        Some(20) => println!("20 age"),
        Some(30) => println!("30 age"),
        Some(_) => println!("other"),
    }

get_user_age()はユーザーのIDから年齢を取得するという関数です。
ユーザーIDからユーザーが見つからない場合はNoneを返します。

結果を受け取った側のmatch文はなにやら見慣れない感じです。
しかしそうなんですRustではこのような書き方が可能なわけです。

(^ _ ^)

やるじゃんRust

(・ v ・)

調教されよう

Resultをmatchで処理する

Resultもmatch演算で処理できます。

    fn get_user_weight(user_id: i32) -> Result<i32, &'static str> {
        match user_id {
            0 => Ok(60),
            1 => Ok(70),
            _ => Err("not found user"),
        }
    }

    match get_user_weight(1) {
        Ok(weight) => println!("user weight is {}", weight),
        Err(err) => println!("{}", err),
    }    

get_user_weight()はユーザーのIDからユーザーの体重を取得する関数です。
ユーザーが存在すればErr("not found user")を返します。

呼び出し側のmatch演算ではOkErrを使って分岐を書くことができます。
関数の処理に成功したらOkのところに行ってエラーになったらErrのところに行きます。

おわりに

今回はRustのmatch演算子について解説しました。
match演算は大変便利な機能です。
覚えて使えるようになっておきましょう。

(^ _ ^)

マッチマッチマッチです

(・ v ・)

踊れmatch演算子



この記事のアンケートを送信する