Option & unwrap

In the last example, we showed that we can induce program failure at will. We told our program to panic if the princess received an inappropriate gift - a snake. But what if the princess expected a gift and didn't receive one? That case would be just as bad, so it needs to be handled!

We could test this against the null string ("") as we do with a snake. Since we're using Rust, let's instead have the compiler point out cases where there's no gift.

An enum called Option<T> in the std library is used when absence is a possibility. It manifests itself as one of two "options":

  • Some(T): 型Tの値がある場合
  • None: 値が存在しない場合。

これらはmatchを用いて明示的に扱うこともできますし、unwrapで暗黙に処理することもできます。後者はSomeの中の値を返すかpanicするかのどちらかです。

expectメソッドを用いて、panicを手動でカスタマイズできることに触れておきましょう。これは(unwrapをそのまま用いた場合よりも)内容が理解しやすいエラーメッセージを出力するのに役立ちます。次の例では、結果をより明示的に、可能ならいつでもpanicできるように扱っていきます。

// The commoner has seen it all, and can handle any gift well.
// All gifts are handled explicitly using `match`.
// 庶民(commoner)は経験豊富なので、大体どんな状況にも対処できます。
// あらゆる贈り物は`match`を用いて手動で処理されます。
fn give_commoner(gift: Option<&str>) {
    // Specify a course of action for each case.
    match gift {
        Some("snake") => println!("Yuck! I'm putting this snake back in the forest."),
        Some(inner)   => println!("{}? How nice.", inner),
        None          => println!("No gift? Oh well."),
    }
}

// Our sheltered princess will `panic` at the sight of snakes.
// All gifts are handled implicitly using `unwrap`.
// 温室育ちのお姫様はヘビを見ると`panic`します。
fn give_princess(gift: Option<&str>) {
    // `unwrap` returns a `panic` when it receives a `None`.
    // `unwrap`を使用すると値が`None`だった際に`panic`を返します。。
    let inside = gift.unwrap();
    if inside == "snake" { panic!("AAAaaaaa!!!!"); }

    println!("I love {}s!!!!!", inside);
}

fn main() {
    let food  = Some("cabbage");
    let snake = Some("snake");
    let void  = None;

    give_commoner(food);
    give_commoner(snake);
    give_commoner(void);

    let bird = Some("robin");
    let nothing = None;

    give_princess(bird);
    give_princess(nothing);
}