Option
と unwrap
以前の例では、甘いレモネードを飲んだ際にpanic
を呼び出すことによって、自由にプログラムの実行を失敗させられることが分かりました。では、何らかの飲み物を期待しているにもかかわらず、何も受け取らなかったらどうなるでしょう?これは悲惨なケースになるので、エラーハンドリングする必要があります!
このケースに対して、レモネードと同じように、空文字列(""
)と比較することもできますが、せっかくRustを使っているので、その代わりにコンパイラに飲み物がないケースを指摘させてみましょう。
std
ライブラリの中の、Option<T>
と呼ばれるenum
は、任意の型T
である変数の値が存在しない可能性がある場合に用いられます。値の状態によって、下記2つのパターンのうちの1つとして扱われます。
Some(T)
: 型T
の値がある場合None
: 値が存在しない場合。
これらはmatch
を用いて明示的に扱うこともできますし、unwrap
で暗黙に処理することもできます。後者はSome
の中の値を返すかpanic
するかのどちらかです。
expectメソッドを用いて、panic
を手動でカスタマイズできることに触れておきましょう。これは(unwrap
をそのまま用いた場合よりも)内容が理解しやすいエラーメッセージを出力するのに役立ちます。次の例では、結果をより明示的に、可能ならいつでもpanic
できるように扱っていきます。
// The adult has seen it all, and can handle any drink well. // All drinks are handled explicitly using `match`. // 大人は経験豊富なので、大体どんな飲み物にも対処できます。 // あらゆる飲み物は`match`を用いて手動で処理されます。 fn give_adult(drink: Option<&str>) { // Specify a course of action for each case. match drink { Some("lemonade") => println!("Yuck! Too sugary."), Some(inner) => println!("{}? How nice.", inner), None => println!("No drink? Oh well."), } } // Others will `panic` before drinking sugary drinks. // All drinks are handled implicitly using `unwrap`. // 他の人たちは甘い飲み物を飲む前に`panic`します。 // 全ての飲み物は`unwrap`を使って暗黙的に処理されます。 fn drink(drink: Option<&str>) { // `unwrap` returns a `panic` when it receives a `None`. // `unwrap`を使用すると値が`None`だった際に`panic`を返します。 let inside = drink.unwrap(); if inside == "lemonade" { panic!("AAAaaaaa!!!!"); } println!("I love {}s!!!!!", inside); } fn main() { let water = Some("water"); let lemonade = Some("lemonade"); let void = None; give_adult(water); give_adult(lemonade); give_adult(void); let coffee = Some("coffee"); let nothing = None; drink(coffee); drink(nothing); }