Result
Result は、起こり得る_不在_ではなく、起こり得る_エラー_を表す、Option 型のより豊かなバージョンです。
つまり、Result<T, E> は次の 2 つの結果のいずれかを持ちます。
Ok(T): 要素Tが見つかったErr(E): 要素Eとともにエラーが見つかった
慣例として、期待される結果は Ok であり、予期しない結果は Err です。
Option と同様に、Result には多くの関連メソッドがあります。たとえば unwrap() は、要素 T を返すか、panic します。ケース処理については、Result と Option の間に重複する多くのコンビネータがあります。
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(()) }