0. まとめ
用途別:
Ok から Ok へおよび Err から Err への変換
map
map_err
map_or_else
Ok から Err へおよび Err から Ok への変換
and_then
or_else
map_or_else
値同士を結合
and_then
or_else
参照
as_ref, as_deref, as_mut, as_deref_mut
複製
clone, clone_from
copied, cloned
※ map_or メソッドも map_or_else メソッドと同じことができますが、値を遅延評価するために本記事では map_or_else メソッドを使用します。
※ and メソッドも and_then メソッドと同じことができますが、値を遅延評価するために本記事では map_or_else メソッドを使用します。
※ or メソッドも or_else メソッドと同じことができますが、値を遅延評価するために本記事では map_or_else メソッドを使用します。
//
pub fn map<U>(self: Result<T, E>, op: impl FnOnce(T) -> U) -> Result<U, E>
pub fn map_err<F>(self: Result<T, E>, op: impl FnOnce(E) -> F) -> Result<T, F>
//
pub fn map_or_else<U>(self: Result<T, E>, default: impl FnOnce(E) -> U, f: impl FnOnce(T) -> U) -> U
//
pub fn and_then<U>(self: Result<T, E>, op: impl FnOnce(T) -> Result<U, E>) -> Result<U, E>
pub fn or_else<F>(self: Result<T, E>, op: impl FnOnce(E) -> Result<T, F>) -> Result<T, F>
//
pub fn as_ref(self: &Result<T, E>) -> Result<&T, &E>
pub fn as_deref(self: &Result<T, E>) -> Result<&T::Target, &E>
where
T: Deref,
pub fn as_mut(self: &mut Result<T, E>) -> Result<&mut T, &mut E>
pub fn as_deref_mut(self: &mut Result<T, E>) -> Result<&mut T::Target, &mut E>
where
T: DerefMut,
//
pub fn clone(self: &Result<T, E>) -> Result<T, E>
pub fn clone_from(self: &mut Result<T, E>, source: &Result<T, E>)
//
pub fn copied(self: Result<&T, E>) -> Result<T, E>
where
T: Copy,
pub fn cloned(self: Result<&T, E>) -> Result<T, E>
where
T: Clone,
pub fn copied(self: Result<&mut T, E>) -> Result<T, E>
where
T: Copy,
pub fn cloned(self: Result<&mut T, E>) -> Result<T, E>
where
T: Clone,
参考「map – Result in std::result – Rust」
参考「map_err – Result in std::result – Rust」
参考「map_or_else – Result in std::result – Rust」
参考「and_then – Result in std::result – Rust」
参考「or_else – Result in std::result – Rust」
参考「as_ref – Result in std::result – Rust」
参考「as_deref – Result in std::result – Rust」
参考「as_mut – Result in std::result – Rust」
参考「as_deref_mut – Result in std::result – Rust」
参考「clone – Result in std::result – Rust」
参考「clone_from – Result in std::result – Rust」
参考「copied – Result in std::result – Rust」
参考「cloned – Result in std::result – Rust」
参考「copied – Result in std::result – Rust」
参考「cloned – Result in std::result – Rust」
1. Ok から Ok へおよび Err から Err への変換
1.1. Result<T, E> 型から Result<U, E> 型への変換
Ok の値のみ変換する場合は map メソッドを用います。
let f = |t: i64| t.to_string();
let x1: Result<i64, i64> = Ok(23);
let x2: Result<i64, i64> = Err(42);
let y1: Result<String, i64> = x1.map(f);
let y2: Result<String, i64> = x2.map(f);
println!("{:?}", y1);
println!("{:?}", y2);
Ok("23")
Err(42)
1.2. Result<T, E> 型から Result<T, F> 型への変換
Err の値のみ変換する場合は map_err メソッドを用います。
let f = |e: i64| e.to_string();
let x1: Result<i64, i64> = Ok(23);
let x2: Result<i64, i64> = Err(42);
let y1: Result<i64, String> = x1.map_err(f);
let y2: Result<i64, String> = x2.map_err(f);
println!("{:?}", y1);
println!("{:?}", y2);
Ok(23)
Err("42")
1.3. Result<T, E> 型から Result<U, F> 型への変換
Ok と Err の両方の値を変換するメソッドは (少なくともバージョン 1.73.0 現在は) 標準では提供されないため、map_or_else メソッドを用いて変換します。
(※ map_or メソッドでも同様のことができますが、map_or メソッドを用いると self が Ok の場合でも Err 用の引数の計算を正格評価で行ってしまうため、map_or_else メソッドを用いて引数を遅延評価します。)
(※ map メソッドと map_err メソッドを組み合わせることでも同様のことができますが、最適化を考慮しない場合は計算コストが増加します。)
let f = |t: i64| t.to_string();
let g = |e: i64| e.to_string();
let x1: Result<i64, i64> = Ok(23);
let x2: Result<i64, i64> = Err(42);
let y1: Result<String, String> = x1.map_or_else(|e| Err(g(e)), |t| Ok(f(t)));
let y2: Result<String, String> = x2.map_or_else(|e| Err(g(e)), |t| Ok(f(t)));
println!("{:?}", y1);
println!("{:?}", y2);
Ok("23")
Err("42")
2. Ok から Err へおよび Err から Ok への変換
2.1. Result<T, E> 型から Result<U, E> 型への変換
Ok の値を Ok または Err の値に変換する場合は and_then メソッドを用います。
let f = |t: i64| if t >= 0 { Ok(t.to_string()) } else { Err(t) };
let x1: Result<i64, i64> = Ok(23);
let x2: Result<i64, i64> = Ok(-23);
let x3: Result<i64, i64> = Err(42);
let x4: Result<i64, i64> = Err(-42);
let y1: Result<String, i64> = x1.and_then(f);
let y2: Result<String, i64> = x2.and_then(f);
let y3: Result<String, i64> = x3.and_then(f);
let y4: Result<String, i64> = x4.and_then(f);
println!("{:?}", y1);
println!("{:?}", y2);
println!("{:?}", y3);
println!("{:?}", y4);
Ok("23")
Err(-23)
Err(42)
Err(-42)
2.2. Result<T, E> 型から Result<T, F> 型への変換
Err の値を Ok または Err の値に変換する場合は or_else メソッドを用います。
let f = |e: i64| if e >= 0 { Ok(e) } else { Err(e.to_string()) };
let x1: Result<i64, i64> = Ok(23);
let x2: Result<i64, i64> = Ok(-23);
let x3: Result<i64, i64> = Err(42);
let x4: Result<i64, i64> = Err(-42);
let y1: Result<i64, String> = x1.or_else(f);
let y2: Result<i64, String> = x2.or_else(f);
let y3: Result<i64, String> = x3.or_else(f);
let y4: Result<i64, String> = x4.or_else(f);
println!("{:?}", y1);
println!("{:?}", y2);
println!("{:?}", y3);
println!("{:?}", y4);
Ok(23)
Ok(-23)
Ok(42)
Err("-42")
2.3. Result<T, E> 型から Result<U, F> 型への変換
Ok と Err の相互変換をする場合は map_or_else メソッドを用います。
let f = |t: i64| {
if t >= 0 {
Ok(t.to_string())
} else {
Err(t.to_string())
}
};
let g = |e: i64| {
if e >= 0 {
Ok(e.to_string())
} else {
Err(e.to_string())
}
};
let x1: Result<i64, i64> = Ok(23);
let x2: Result<i64, i64> = Ok(-23);
let x3: Result<i64, i64> = Err(42);
let x4: Result<i64, i64> = Err(-42);
let y1: Result<String, String> = x1.map_or_else(g, f);
let y2: Result<String, String> = x2.map_or_else(g, f);
let y3: Result<String, String> = x3.map_or_else(g, f);
let y4: Result<String, String> = x4.map_or_else(g, f);
println!("{:?}", y1);
println!("{:?}", y2);
println!("{:?}", y3);
println!("{:?}", y4);
Ok("23")
Err("-23")
Ok("42")
Err("-42")
3. 値同士を結合する
3.1. Result<T, E> 型から Result<U, E> 型への変換
and_then メソッドは、2 値が両方とも Ok なら Ok を返し、それ以外は Err を返す目的でも使用できます。
(※ and メソッドでも同様のことができますが、and メソッドを用いると self が Err の場合でも引数の計算を正格評価で行ってしまうため、and_then メソッドを用いて引数を遅延評価します。)
let x1: Result<i64, &str> = Ok(23);
let x2: Result<i64, &str> = Err("Error: x");
let y1: Result<&str, &str> = x1.and_then(|_| Ok("Foo"));
let y2: Result<&str, &str> = x1.and_then(|_| Err("Error: y"));
let y3: Result<&str, &str> = x2.and_then(|_| Ok("Foo"));
let y4: Result<&str, &str> = x2.and_then(|_| Err("Error: y"));
println!("{:?}", y1);
println!("{:?}", y2);
println!("{:?}", y3);
println!("{:?}", y4);
Ok("Foo")
Err("Error: y")
Err("Error: x")
Err("Error: x")
3.2. Result<T, E> 型から Result<T, F> 型への変換
or_else メソッドは、2 値のどちらか一方が Ok なら Ok を返し、それ以外は Err を返す目的でも使用できます。
(※ or メソッドでも同様のことができますが、or メソッドを用いると self が Ok の場合でも引数の計算を正格評価で行ってしまうため、or_else メソッドを用いて引数を遅延評価します。)
let x1: Result<&str, i64> = Ok("Foo");
let x2: Result<&str, i64> = Err(23);
let y1: Result<&str, &str> = x1.or_else(|_| Ok("Bar"));
let y2: Result<&str, &str> = x1.or_else(|_| Err("Error: y"));
let y3: Result<&str, &str> = x2.or_else(|_| Ok("Bar"));
let y4: Result<&str, &str> = x2.or_else(|_| Err("Error: y"));
println!("{:?}", y1);
println!("{:?}", y2);
println!("{:?}", y3);
println!("{:?}", y4);
Ok("Foo")
Ok("Foo")
Ok("Bar")
Err("Error: y")
4. 参照
Ok および Err の中身の値を借用します。
Ok に関しては中身の値を借用かつ deref() することもできます。
let x1: Result<String, i64> = Ok("Foo".to_string());
let x2: Result<String, i64> = Err(23);
//
let y1: Result<&String, &i64> = x1.as_ref();
let y2: Result<&String, &i64> = x2.as_ref();
let y1: Result<&str, &i64> = x1.as_deref();
let y2: Result<&str, &i64> = x2.as_deref();
let mut x1: Result<String, i64> = Ok("Foo".to_string());
let mut x2: Result<String, i64> = Err(23);
//
let y1: Result<&mut String, &mut i64> = x1.as_mut();
let y2: Result<&mut String, &mut i64> = x2.as_mut();
let y1: Result<&mut str, &mut i64> = x1.as_deref_mut();
let y2: Result<&mut str, &mut i64> = x2.as_deref_mut();
5. 複製
Ok および Err の外身の値を複製する場合は clone メソッドまたは clone_from メソッドを用います。
let x: Result<i64, i64> = Ok(23);
//
let y: Result<i64, i64> = x.clone();
let mut y: Result<i64, i64> = x.clone();
y.clone_from(&x);
Ok の中身の値を複製する場合は copied メソッドまたは cloned メソッドを用います。
//
let value = 23;
let x: Result<&i64, i64> = Ok(&value);
let y: Result<i64, i64> = x.copied();
let value = 23;
let x: Result<&i64, i64> = Ok(&value);
let y: Result<i64, i64> = x.cloned();
//
let value = "Foo".to_string();
let x: Result<&String, i64> = Ok(&value);
let y: Result<String, i64> = x.cloned();
//
let mut value = 23;
let x: Result<&mut i64, i64> = Ok(&mut value);
let y: Result<i64, i64> = x.copied();
let mut value = 23;
let x: Result<&mut i64, i64> = Ok(&mut value);
let y: Result<i64, i64> = x.cloned();
//
let mut value = "Foo".to_string();
let x: Result<&mut String, i64> = Ok(&mut value);
let y: Result<String, i64> = x.cloned();