Result
Resultは値の不在をエラーに置き換えたOption型
の上位互換です。
つまり、Result<T, E>は2つの結果を持つことができます。
Ok(T):Tが存在する場合Err(E):Eというエラーが見つかった場合
利便性のため、期待する値をOk、予期せぬ値をErrに入れます。
Optionと同じように、Resultは多くのメソッドを持っています。例えば、
unwrap()はT型の値を返すか、panicします。また、条件処理のために、
Optionと同じようなコンビネータがResultにもあります。
Rustを使っていると、おそらく、parse()のようにResult型を返す
ようなメソッドに出会うでしょう。文字列をいつも他の型に変換できるとは限らない
ため、parse()は失敗を処理するためにResultを使っています。
成功した場合と失敗した場合の文字列のparse()の振る舞いを見てみましょう。
fn multiply(first_number_str: &str, second_number_str: &str) -> i32 { // `unwrap()`を使って数値を取り出してみましょう。 let first_number = first_number_str.parse::<i32>().unwrap(); let second_number = second_number_str.parse::<i32>().unwrap(); first_number * second_number } fn main() { let twenty = multiply("10", "2"); println!("double is {}", twenty); let tt = multiply("t", "2"); println!("double is {}", tt); }
parse()が失敗した場合は、unwrap()でpanicを起こしてプログラムを終了しました。
さらに、panicは不快なエラーメッセージを返しました。
エラーメッセージの質を改善するため、返り値の型をさらに特定し、明示的に エラーを処理する必要があります。
mainでResultを使う
明示的に指定することで、Result型をmain関数で使うこともできます。
典型的なmain関数はこのような形です。
fn main() { println!("Hello World!"); }
しかし、mainは返り値としてResultを使うこともできます。main関数内でエラーが
起これば、エラーコードを返し、デバッグプリントでエラーを報告します。(Debug
トレイトを使います。) 以下の例では、次の例では、そのようなシナリオを紹介し、
後の節で扱う内容にも触れます。
use std::num::ParseIntError; fn main() -> Result<(), ParseIntError> { let number_str = "10"; let number = match number_str.parse::<i32>() { Ok(number) => number, Err(e) => return Err(e), }; println!("{}", number); Ok(()) }