Resultのmap
前の例のmultiplyでのパニックは実用コードのために作られていません。
普通、呼び出し元にエラーを返し、エラー処理を呼び出し元に任せます。
まず、どのようなタイプのエラーがあるのか知る必要があります。Errの型を決めるため、
FromStrトレイトをi32に実装することで提供されているparse()
関数を見てみます。すると、Errの型はParseIntErrorだと
定義されていることがわかります。
以下の例では、愚直にmatch文を使っていますが、これは面倒です。
use std::num::ParseIntError; // 返り値の型を書き直し、`unwrap()`を使わずパターンマッチしています。 fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> { match first_number_str.parse::<i32>() { Ok(first_number) => { match second_number_str.parse::<i32>() { Ok(second_number) => { Ok(first_number * second_number) }, Err(e) => Err(e), } }, Err(e) => Err(e), } } fn print(result: Result<i32, ParseIntError>) { match result { Ok(n) => println!("n is {}", n), Err(e) => println!("Error: {}", e), } } fn main() { // これはまだ使えます。 let twenty = multiply("10", "2"); print(twenty); // これは有用なエラーメッセージを返すようになりました。 let tt = multiply("t", "2"); print(tt); }
幸運なことに、Optionのmapやand_thenなどのコンビネータはResultにも
実装されています。Resultに完全な一覧があります。
use std::num::ParseIntError; // `Option`のように、`map()`コンビネータが使えます。 // この関数は上と同じ動作をします。 // 値が有効な場合nを渡し、その他の場合はエラーを渡す。 fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> { first_number_str.parse::<i32>().and_then(|first_number| { second_number_str.parse::<i32>().map(|second_number| 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() { // これはまだ使えます。 let twenty = multiply("10", "2"); print(twenty); // これは有用なエラーメッセージを返すようになりました。 let tt = multiply("t", "2"); print(tt); }