?の導入
時には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関数を実装すると、以下のようになるでしょう。
// To compile and run this example without errors, while using Cargo, change the value
// of the `edition` field, in the `[package]` section of the `Cargo.toml` file, to "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 ?を参照。 ↩