※ 項目の末尾の *
は Result あるいは Option にしかないメソッドであることを表す。
概要
Rust には様々な標準ライブラリが用意されています。
その中には Result 型や Option 型といった便利な型があります。
これらにはいくつかのメソッドが用意されており、エラーや None の値を簡潔かつ適切に処理することができます。
この記事では Result 型と Option 型のいくつかのメソッドについてまとめて、列挙していきます。
std::Result
Rust には Result 型と言われるものがあり、これは関数が成功するか失敗するかの結果を表現する列挙型です。
一般的には、成功時には Ok 値を、失敗時には Err 値を返します。
Result 型は、 Rust のエラーハンドリングにおいて非常に重要な役割を担っています。
pub enum Result<T, E> { Ok(T), Err(E), }
map
Ok
の場合には関数を適用してErr
の場合にはそのままにしてResult
を返す
pub fn map<U, F>(self, op: F) -> Result<U, E> where F: FnOnce(T) -> U,
Example
let line = "1\n2\n3\n4\n"; for num in line.lines() { match num.parse::<i32>().map(|i| i * 2) { Ok(n) => println!("{n}"), Err(..) => {} } }
map_err*
Ok
の場合にはそのままにしてErr
の場合には関数を適用してResult
を返す
pub fn map_err<F, O>(self, op: O) -> Result<T, F> where O: FnOnce(E) -> F,
Example
fn stringify(x: u32) -> String { format!("error code: {x}") } let x: Result<u32, u32> = Ok(2); assert_eq!(x.map_err(stringify), Ok(2)); let x: Result<u32, u32> = Err(13); assert_eq!(x.map_err(stringify), Err("error code: 13".to_string()));
map_or
Ok
の場合には関数を適用してErr
の場合にはデフォルト値を返す
pub fn map_or<U, F>(self, default: U, f: F) -> U where F: FnOnce(T) -> U,
Example
let x: Result<_, &str> = Ok("foo"); assert_eq!(x.map_or(42, |v| v.len()), 3); let x: Result<&str, _> = Err("bar"); assert_eq!(x.map_or(42, |v| v.len()), 42);
map_or_else
Ok
の場合には関数を適用してErr
の場合にはフォールバック関数を適用する
pub fn map_or_else<U, D, F>(self, default: D, f: F) -> U where D: FnOnce(E) -> U, F: FnOnce(T) -> U,
Example
let k = 21; let x : Result<_, &str> = Ok("foo"); assert_eq!(x.map_or_else(|e| k * 2, |v| v.len()), 3); let x : Result<&str, _> = Err("bar"); assert_eq!(x.map_or_else(|e| k * 2, |v| v.len()), 42);
unwrap
Ok
の場合には値をそのまま返してErr
の場合にはパニックを起こす
pub fn unwrap(self) -> T where E: Debug,
Example
let x: Result<u32, &str> = Ok(2); assert_eq!(x.unwrap(), 2); // This example panics let x: Result<u32, &str> = Err("emergency failure"); x.unwrap(); // panics with `emergency failure`
unwrap_err*
Ok
の場合にはパニックを起こしてErr
の場合には値をそのまま返す
pub fn unwrap_err(self) -> E where T: Debug,
Example
// This example panics let x: Result<u32, &str> = Ok(2); x.unwrap_err(); // panics with `2` let x: Result<u32, &str> = Err("emergency failure"); assert_eq!(x.unwrap_err(), "emergency failure");
unwrap_or
Ok
の場合には値をそのまま返してErr
の場合には引数の値をデフォルト値として返す
pub fn unwrap_or(self, default: T) -> T
Example
let default = 2; let x: Result<u32, &str> = Ok(9); assert_eq!(x.unwrap_or(default), 9); let x: Result<u32, &str> = Err("error"); assert_eq!(x.unwrap_or(default), default);
unwrap_or_else
Ok
の場合には値をそのまま返してErr
の場合には引数で受けたクロージャの返り値を返す
pub fn unwrap_or_else<F>(self, op: F) -> T where F: FnOnce(E) -> T,
Example
fn count(x: &str) -> usize { x.len() } assert_eq!(Ok(2).unwrap_or_else(count), 2); assert_eq!(Err("foo").unwrap_or_else(count), 3);
unwrap_or_default
Ok
の場合には値をそのまま返してErr
の場合にはOk
の型のデフォルト値を返す
pub fn unwrap_or_default(self) -> T where T: Default,
Example
let good_year_from_input = "1909"; let bad_year_from_input = "190blarg"; let good_year = good_year_from_input.parse().unwrap_or_default(); let bad_year = bad_year_from_input.parse().unwrap_or_default(); assert_eq!(1909, good_year); assert_eq!(0, bad_year);
and_then
Ok
の場合には関数を呼び出してErr
の場合には値をそのままにしてResult
を返すOk
型が返ってくるmap
と異なり、関数の返り値もResult
になっている
pub fn and_then<U, F>(self, op: F) -> Result<U, E> where F: FnOnce(T) -> Result<U, E>,
Example 1
fn sq_then_to_string(x: u32) -> Result<String, &'static str> { x.checked_mul(x).map(|sq| sq.to_string()).ok_or("overflowed") } assert_eq!(Ok(2).and_then(sq_then_to_string), Ok(4.to_string())); assert_eq!(Ok(1_000_000).and_then(sq_then_to_string), Err("overflowed")); assert_eq!(Err("not a number").and_then(sq_then_to_string), Err("not a number"));
Example2: Err
を返すかもしれないメソッドチェーンの操作内で用いられる
use std::{io::ErrorKind, path::Path}; // Note: on Windows "/" maps to "C:\" let root_modified_time = Path::new("/").metadata().and_then(|md| md.modified()); assert!(root_modified_time.is_ok()); let should_fail = Path::new("/bad/path").metadata().and_then(|md| md.modified()); assert!(should_fail.is_err()); assert_eq!(should_fail.unwrap_err().kind(), ErrorKind::NotFound);
or_else
Ok
の場合には値をそのままにしてErr
の場合には関数を呼び出してResult
を返すErr
型が返ってくるmap_err
と異なり、関数の返り値もResult
になっている
pub fn or_else<F, O>(self, op: O) -> Result<T, F> where O: FnOnce(E) -> Result<T, F>,
Example
fn sq(x: u32) -> Result<u32, u32> { Ok(x * x) } fn err(x: u32) -> Result<u32, u32> { Err(x) } assert_eq!(Ok(2).or_else(sq).or_else(sq), Ok(2)); assert_eq!(Ok(2).or_else(err).or_else(sq), Ok(2)); assert_eq!(Err(3).or_else(sq).or_else(err), Ok(9)); assert_eq!(Err(3).or_else(err).or_else(err), Err(3));
ok
Result<T, E>
をOption<T>
に変換するErr
は潰れてNone
になる
pub fn ok(self) -> Option<T>
Example
let x: Result<u32, &str> = Ok(2); assert_eq!(x.ok(), Some(2)); let x: Result<u32, &str> = Err("Nothing here"); assert_eq!(x.ok(), None);
err
Result<T, E>
をOption<E>
に変換するOk
は潰れてNone
になる
pub fn err(self) -> Option<E>
Example
let x: Result<u32, &str> = Ok(2); assert_eq!(x.err(), None); let x: Result<u32, &str> = Err("Nothing here"); assert_eq!(x.err(), Some("Nothing here"));
std::Option
また、 Rust には Option 型と言われるものがあり、これは値が存在するかどうかを表現するための列挙型です。
Some 値を持つ場合は Some(v) という値を、値が存在しない場合は None という値を持ちます。
Option 型は、Rust においてエラーハンドリングに使われるだけでなく、 Rust のパターンマッチングにおいても頻繁に使われます。
pub enum Option<T> { None, Some(T), }
map
Some
の場合には関数を適用してNone
の場合にはそのままにしてOption
を返す
pub fn map<U, F>(self, f: F) -> Option<U> where F: FnOnce(T) -> U,
Example
/* Converts an Option<String> into an Option<usize>, consuming the original: */ let maybe_some_string = Some(String::from("Hello, World!")); // `Option::map` takes self *by value*, consuming `maybe_some_string` let maybe_some_len = maybe_some_string.map(|s| s.len()); assert_eq!(maybe_some_len, Some(13));
map_or
Some
の場合には関数を適用してNone
の場合にはデフォルト値を返す
pub fn map_or<U, F>(self, default: U, f: F) -> U where F: FnOnce(T) -> U,
Example
let x = Some("foo"); assert_eq!(x.map_or(42, |v| v.len()), 3); let x: Option<&str> = None; assert_eq!(x.map_or(42, |v| v.len()), 42);
map_or_else
Some
の場合には関数を適用してNone
の場合には別のデフォルト関数を適用する
pub fn map_or_else<U, D, F>(self, default: D, f: F) -> U where D: FnOnce() -> U, F: FnOnce(T) -> U,
Example
let k = 21; let x = Some("foo"); assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 3); let x: Option<&str> = None; assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42);
unwrap
Some
の場合には値をそのまま返してNone
の場合にはパニックを起こす
pub fn unwrap(self) -> T
Example
let x = Some("air"); assert_eq!(x.unwrap(), "air"); // This example panics let x: Option<&str> = None; assert_eq!(x.unwrap(), "air"); // fails
unwrap_or
Some
の場合には値をそのまま返してNone
の場合には引数の値をデフォルト値として返す
pub fn unwrap_or(self, default: T) -> T
Example
assert_eq!(Some("car").unwrap_or("bike"), "car"); assert_eq!(None.unwrap_or("bike"), "bike");
unwrap_or_else
Some
の場合には値をそのまま返してNone
の場合には引数で受けたクロージャの返り値を返す
pub fn unwrap_or_else<F>(self, f: F) -> T where F: FnOnce() -> T,
Example
let k = 10; assert_eq!(Some(4).unwrap_or_else(|| 2 * k), 4); assert_eq!(None.unwrap_or_else(|| 2 * k), 20);
unwrap_or_default
Some
の場合には値をそのまま返してNone
の場合にはSome
の型のデフォルト値を返す
pub fn unwrap_or_default(self) -> T where T: Default,
Example
let good_year_from_input = "1909"; let bad_year_from_input = "190blarg"; let good_year = good_year_from_input.parse().ok().unwrap_or_default(); let bad_year = bad_year_from_input.parse().ok().unwrap_or_default(); assert_eq!(1909, good_year); assert_eq!(0, bad_year);
and_then
Some
の場合には関数を呼び出してNone
の場合には値をそのままにしてOption
を返すSome
型が返ってくるmap
と異なり、関数の返り値もOption
になっている
pub fn and_then<U, F>(self, f: F) -> Option<U> where F: FnOnce(T) -> Option<U>,
Example1
fn sq_then_to_string(x: u32) -> Option<String> { x.checked_mul(x).map(|sq| sq.to_string()) } assert_eq!(Some(2).and_then(sq_then_to_string), Some(4.to_string())); assert_eq!(Some(1_000_000).and_then(sq_then_to_string), None); // overflowed! assert_eq!(None.and_then(sq_then_to_string), None);
Example2: Err
を返すかもしれないメソッドチェーンの操作内で用いられる
let arr_2d = [["A0", "A1"], ["B0", "B1"]]; let item_0_1 = arr_2d.get(0).and_then(|row| row.get(1)); assert_eq!(item_0_1, Some(&"A1")); let item_2_0 = arr_2d.get(2).and_then(|row| row.get(0)); assert_eq!(item_2_0, None);
or_else
Some
の場合には値をそのままにしてNone
の場合には関数を呼び出してOption
を返す
pub fn or_else<F>(self, f: F) -> Option<T> where F: FnOnce() -> Option<T>,
Example
fn nobody() -> Option<&'static str> { None } fn vikings() -> Option<&'static str> { Some("vikings") } assert_eq!(Some("barbarians").or_else(vikings), Some("barbarians")); assert_eq!(None.or_else(vikings), Some("vikings")); assert_eq!(None.or_else(nobody), None);
ok_or*
Some(v)
をOk(v)
に、None
をErr(err)
にマッピングしてOption<T>
をResult<T, E>
に変換する
pub fn ok_or<E>(self, err: E) -> Result<T, E>
Example
let x = Some("foo"); assert_eq!(x.ok_or(0), Ok("foo")); let x: Option<&str> = None; assert_eq!(x.ok_or(0), Err(0));
ok_or_else*
Some(v)
をOk(v)
に、None
をErr(err())
にマッピングしてOption<T>
をResult<T, E>
に変換する
pub fn ok_or_else<E, F>(self, err: F) -> Result<T, E> where F: FnOnce() -> E,
Example
let x = Some("foo"); assert_eq!(x.ok_or_else(|| 0), Ok("foo")); let x: Option<&str> = None; assert_eq!(x.ok_or_else(|| 0), Err(0));
Tips
Result
→Option
はmap_or_else
で None と Some を返すようにして変換できるOption
→Result
はok_or
あるいはok_or_else
で変換できる