RustでNoneやエラーに対してデフォルト値・任意の値を返す
RustでOptionのNoneやResultのエラーErrに対してデフォルト値・任意の値を返すには、unwrap_or_default, unwrap_or, unwrap_or_elseを使う。
型のデフォルト値を返す: unwrap_or_default
unwrap_or_defaultはSomeやOkに対してはその値、NoneやエラーErrに対しては型のデフォルト値を返す。
型のデフォルト値: Defaultトレイト
型のデフォルト値はDefaultトレイトで定められている。
例えば、数値型は0、ベクタVecや文字列Stringは空のベクタや文字列がデフォルト値となっている。
- f32 - impl Default for f32 - Rust
- Vec - impl<T> Default for Vec<T, Global> in std::vec - Rust
- String - impl Default for String in std::string - Rust
Option::unwrap_or_defaultの例
ベクタVecからpopで要素を取り出す。popはベクタが空のときNoneを返す。
要素数1個のベクタだと、1回目のpopはSome、2回目のpopはNoneを返す。
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_elseはNoneやエラーのときに引数に指定したクロージャや関数を実行してその値を返す。
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_defaultとunwrap_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"
);
Resultのunwrap_or_elseは、指定したクロージャや関数に引数としてエラー値(Err(e)のe)を渡すので注意。
eを使わない場合も|_| ...のように引数を記述する必要がある。