? の導入
panic の可能性なしに、unwrap の単純さだけが欲しい場合があります。 これまで、私たちが本当に望んでいたのは変数を 外へ 取り出すことだったのに、 unwrap はより深くネストすることを強いてきました。これこそが ? の目的です。
Err を見つけたとき、取るべき有効なアクションは 2 つあります。
panic!。これは、可能なら避けようとすでに決めたものですreturn。Errは処理できないことを意味するためです
? は、Err で panic する代わりに return する unwrap と ほぼ1 正確に同等です。コンビネータを使った先ほどの例をどのように簡略化できるか見てみましょう。
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! に出会うかもしれません。 前の例と同じ multiply 関数を try! を使って書くと、次のようになります。
// 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")); }
-
詳細については、re-enter ? を参照してください。 ↩