// dictionary
Result型.
Result<T, E>は、処理が成功したか失敗したかを表す標準ライブラリの列挙型です1。成功時の値を包むOk(T)と、失敗時のエラー値を包むErr(E)という2つのバリアントを持ちます。同じく2バリアントのOption型が値の「有無」だけを表すのに対し、Resultは失敗した「理由」までエラー値として表現できる点が異なります。
fn split_bill(total: i32, people: i32) -> Result<i32, String> {
if people == 0 {
Err("人数が0人です".to_string())
} else {
Ok(total / people)
}
}
fn main() {
for people in [4, 0] {
match split_bill(3000, people) {
Ok(amount) => println!("1人あたり{amount}円"),
Err(reason) => println!("エラー: {reason}"),
}
}
}Playgroundで開く?演算子によるエラー伝播
Resultを返す関数の中では、?演算子を使うことでErrの場合にエラー値をFromで変換したうえで即座に呼び出し元へ返せます。match式を毎回書かずに済むため、失敗しうる処理を連続して呼び出すコードを簡潔に書けます。
fn split_bill(total: i32, people: i32) -> Result<i32, String> {
if people == 0 {
return Err("人数が0人です".to_string());
}
Ok(total / people)
}
fn print_share(total: i32, people: i32) -> Result<(), String> {
let amount = split_bill(total, people)?; // Errならここで即座にreturnする
println!("1人あたり{amount}円");
Ok(())
}
fn main() {
if let Err(reason) = print_share(3000, 0) {
println!("エラー: {reason}");
}
}Playgroundで開く#[must_use]による握りつぶし防止
補足
用途別のResultエイリアス
std::io関連の関数はほとんどがio::Errorをエラー型として返すため、標準ライブラリはpub type Result<T> = result::Result<T, Error>という型エイリアスをstd::io::Result<T>として提供しています2。エラー型を毎回書かずに済み、プレリュードのstd::result::Resultと名前が重複してもio::Resultと書けば区別できます。
Footnotes
-
std::result::Result —
#[must_use = "this \Result` may be an `Err` variant, which should be handled“]付きでpub enum Result<T, E> { Ok(T), Err(E) }`と定義されています。 ↩ ↩2 -
std::io::Result —
pub type Result<T> = result::Result<T, Error>と定義されています。 ↩
この辞書が使われているページ
backlinks 7