rs.nkmk.me

RustでNoneやエラーに対してデフォルト値・任意の値を返す

Posted: | Tags: Rust, エラー処理

RustでOptionNoneResultのエラーErrに対してデフォルト値・任意の値を返すには、unwrap_or_default, unwrap_or, unwrap_or_elseを使う。

型のデフォルト値を返す: unwrap_or_default

unwrap_or_defaultSomeOkに対してはその値、NoneやエラーErrに対しては型のデフォルト値を返す。

型のデフォルト値: Defaultトレイト

型のデフォルト値はDefaultトレイトで定められている。

例えば、数値型は0、ベクタVecや文字列Stringは空のベクタや文字列がデフォルト値となっている。

Option::unwrap_or_defaultの例

ベクタVecからpopで要素を取り出す。popはベクタが空のときNoneを返す。

要素数1個のベクタだと、1回目のpopSome、2回目のpopNoneを返す。

unwrap_or_defaultを使うと、Noneのときは要素の型のデフォルト値が返される。

let mut v: Vec<i32> = vec![100];

assert_eq!(v.pop().unwrap_or_default(), 100);
assert_eq!(v.pop().unwrap_or_default(), 0);

let mut v: Vec<String> = vec![String::from("abc")];

assert_eq!(v.pop().unwrap_or_default(), "abc");
assert_eq!(v.pop().unwrap_or_default(), "");

Result::unwrap_or_defaultの例

文字列をparseで数値に変換する。parseは変換できないときエラーを返す。

assert_eq!("100".parse::<i32>().unwrap_or_default(), 100);
assert_eq!("abc".parse::<i32>().unwrap_or_default(), 0);

任意の値を返す: unwrap_or

型のデフォルト値ではなく任意の値を返したいときはunwrap_orを使う。返したい値を引数に指定する。

Option::unwrap_orの例

let mut v: Vec<i32> = vec![100];

assert_eq!(v.pop().unwrap_or(5), 100);
assert_eq!(v.pop().unwrap_or(5), 5);

文字列Stringを返したい場合は次に説明するunwrap_or_elseの使用が推奨されている。

Result::unwrap_orの例

assert_eq!("100".parse::<i32>().unwrap_or(5), 100);
assert_eq!("abc".parse::<i32>().unwrap_or(5), 5);

クロージャ・関数を実行して返す: unwrap_or_else

unwrap_or_elseNoneやエラーのときに引数に指定したクロージャや関数を実行してその値を返す。

unwrap_orは先行評価で指定した式が常に実行されるのに対し、unwrap_or_elseは遅延評価でNoneやエラーのときのみ実行される。関数呼び出しの結果を使いたい場合はunwrap_or_elseの使用が推奨されている。

Option::unwrap_or_elseの例

let mut v: Vec<String> = vec![String::from("abc")];

assert_eq!(v.pop().unwrap_or_else(|| String::from("N/A")), "abc");
assert_eq!(v.pop().unwrap_or_else(|| String::from("N/A")), "N/A");

|| ...は引数なしのクロージャ。

Result::unwrap_or_elseの例

fs::read_to_stringを例とする。パスを指定すると中身を読み込み文字列Stringとして返す。存在しないパスを指定するとエラーを返す。

存在しないパスに対するunwrap_or_defaultunwrap_or_elseの例を示す。存在するパスの例は省略。

use std::fs;

let path = "path/to/non_existent_file";

assert_eq!(fs::read_to_string(path).unwrap_or_default(), "");
assert_eq!(
    fs::read_to_string(path).unwrap_or_else(|_| String::from("N/A")),
    "N/A"
);

Resultunwrap_or_elseは、指定したクロージャや関数に引数としてエラー値(Err(e)e)を渡すので注意。

eを使わない場合も|_| ...のように引数を記述する必要がある。

関連カテゴリー

関連記事