?
の導入
時にはpanic
の可能性を無視して、unwrap
のシンプルさを活用したいこともあるでしょう。今までのunwrap
は、値を_取り出す_ためだけであろうとも、ネストを深く書くことを要求しました。そして、これがまさに?
の目的です。
Err
を見つけるにあたり、2つのとるべき行動があります。
- 可能な限り避けたいと決めた
panic!
Err
は処理できないことを意味するためreturn
?
は_ほぼ_1まさしく、Err
に対してpanic
するよりreturn
するという点でunwrap
と同等です。コンビネータを使った以前の例をどれだけ簡潔に書けるか見てみましょう。
use std::num::ParseIntError; fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> { let first_number = first_number_str.parse::<i32>()?; let second_number = second_number_str.parse::<i32>()?; Ok(first_number * second_number) } fn print(result: Result<i32, ParseIntError>) { match result { Ok(n) => println!("n is {}", n), Err(e) => println!("Error: {}", e), } } fn main() { print(multiply("10", "2")); print(multiply("t", "2")); }
try!
マクロ
?
ができる前、同様の動作をtry!
マクロによって行うことができました。現在は?
演算子が推奨されていますが、古いコードではtry!
に出会うこともあります。try!
を使って前の例と同じmultiply
関数を実装すると、以下のようになるでしょう。
// Cargoを使いながらこの例をエラーなくコンパイル、及び実行する場合、 // `Cargo.toml`ファイル内、`[package]`セクションの`edition`の値を"2015"に変更してください。 use std::num::ParseIntError; fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> { let first_number = try!(first_number_str.parse::<i32>()); let second_number = try!(second_number_str.parse::<i32>()); Ok(first_number * second_number) } fn print(result: Result<i32, ParseIntError>) { match result { Ok(n) => println!("n is {}", n), Err(e) => println!("Error: {}", e), } } fn main() { print(multiply("10", "2")); print(multiply("t", "2")); }
1
詳細はre-enter ?を参照。