[Rust] Result<T, E> 型から Result<U, F> 型への変換

# 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` メソッドを使用します。

```rust
// 
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](https://doc.rust-lang.org/std/result/enum.Result.html#method.map)」
参考「[map_err - Result in std::result - Rust](https://doc.rust-lang.org/std/result/enum.Result.html#method.map_err)」

参考「[map_or_else - Result in std::result - Rust](https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or_else)」

参考「[and_then - Result in std::result - Rust](https://doc.rust-lang.org/std/result/enum.Result.html#method.and_then)」
参考「[or_else - Result in std::result - Rust](https://doc.rust-lang.org/std/result/enum.Result.html#method.or_else)」

参考「[as_ref - Result in std::result - Rust](https://doc.rust-lang.org/std/result/enum.Result.html#method.as_ref)」
参考「[as_deref - Result in std::result - Rust](https://doc.rust-lang.org/std/result/enum.Result.html#method.as_deref)」
参考「[as_mut - Result in std::result - Rust](https://doc.rust-lang.org/std/result/enum.Result.html#method.as_mut)」
参考「[as_deref_mut - Result in std::result - Rust](https://doc.rust-lang.org/std/result/enum.Result.html#method.as_deref_mut)」

参考「[clone - Result in std::result - Rust](https://doc.rust-lang.org/std/result/enum.Result.html#method.clone)」
参考「[clone_from - Result in std::result - Rust](https://doc.rust-lang.org/std/result/enum.Result.html#method.clone_from)」

参考「[copied - Result in std::result - Rust](https://doc.rust-lang.org/std/result/enum.Result.html#method.copied)」
参考「[cloned - Result in std::result - Rust](https://doc.rust-lang.org/std/result/enum.Result.html#method.cloned)」
参考「[copied - Result in std::result - Rust](https://doc.rust-lang.org/std/result/enum.Result.html#method.copied-1)」
参考「[cloned - Result in std::result - Rust](https://doc.rust-lang.org/std/result/enum.Result.html#method.cloned-1)」

# 1. `Ok` から `Ok` へおよび `Err` から `Err` への変換

## 1.1. `Result<T, E>` 型から `Result<U, E>` 型への変換

`Ok` の値のみ変換する場合は `map` メソッドを用います。

```rust
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);
```

```text:実行結果
Ok("23")
Err(42)
```

## 1.2. `Result<T, E>` 型から `Result<T, F>` 型への変換

`Err` の値のみ変換する場合は `map_err` メソッドを用います。

```rust
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);
```

```text:実行結果
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` メソッドを組み合わせることでも同様のことができますが、最適化を考慮しない場合は計算コストが増加します。)

```rust
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);
```

```text:実行結果
Ok("23")
Err("42")
```

# 2. `Ok` から `Err` へおよび `Err` から `Ok` への変換

## 2.1. `Result<T, E>` 型から `Result<U, E>` 型への変換

`Ok` の値を `Ok` または `Err` の値に変換する場合は `and_then` メソッドを用います。

```rust
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);
```

```text:実行結果
Ok("23")
Err(-23)
Err(42)
Err(-42)
```

## 2.2. `Result<T, E>` 型から `Result<T, F>` 型への変換

`Err` の値を `Ok` または `Err` の値に変換する場合は `or_else` メソッドを用います。

```rust
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);
```

```text:実行結果
Ok(23)
Ok(-23)
Ok(42)
Err("-42")
```

## 2.3. `Result<T, E>` 型から `Result<U, F>` 型への変換

`Ok` と `Err` の相互変換をする場合は `map_or_else` メソッドを用います。

```rust
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);
```

```text:実行結果
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` メソッドを用いて引数を遅延評価します。)

```rust
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);
```

```text:実行結果
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` メソッドを用いて引数を遅延評価します。)

```rust
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);
```

```text:実行結果
Ok("Foo")
Ok("Foo")
Ok("Bar")
Err("Error: y")
```

# 4. 参照

`Ok` および `Err` の中身の値を借用します。

`Ok` に関しては中身の値を借用かつ `deref()` することもできます。

```rust
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();
```

```rust
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` メソッドを用います。

```rust
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` メソッドを用います。

```rust
//
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();
```