エラーハンドリング付きの filter_map のアプローチ

Rust の [`std::iter::Iterator`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html) トレイトには [`filter_map`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.filter_map) という関数が用意されている。この関数に渡すクロージャ内でエラーが発生するようなケースを取り扱いたい場合に、どのようにすれば対応できるのかを以下で説明する。

## そもそも `filter_map` とは?

Rust ではイテレータを使って配列やベクタなどを処理するのは当たり前のように行われる。
流れとしては
* `.into_iter()`, `.iter()` のように配列やベクタからイテレータを生成するステップ
* `.skip()`, `.map()`, `filter()` のように要素に処理を行う、別のイテレータを生成するステップ
* `.for_each()`, `.collect()`, `.reduce()` のようにイテレータを消費するステップ
の3つに分類される。

以下に [`map`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.map) を使う場合の例となるコードを与える。

```rust
let num_list: Vec<u8> = vec![3,4,5,7];

let squared_num_list: Vec<u8> =
	// ベクタからイテレータを生成
	num_list.into_iter()
	// イテレータを消費し、処理を行った別のイテレータを生成
	.map( |num| num*num )
	// イテレータを消費して新しいベクタにする
	.collect::<Vec<u8>>();
```

Rust には要素を写像する [`map`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.map) と、要素を取捨選択する [`filter`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.filter) を組み合わせた [`filter_map`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.filter_map) が存在する。
`map` も `filter` もイテレータ要素か、その参照を引数にとるクロージャを与え、 `map` なら変換後の新しい値を返し、 `filter` なら取るか捨てるかの `bool` 型の値を返す。
Rust には `Some(T)` と `None` から構成される [`Option<T>`](https://doc.rust-lang.org/stable/std/option/enum.Option.html) 型があるので、これら2つの機能を組み合わせた `filter_map` 関数が用意できる。

```rust
trait Iterator {
	// イテレートする内容の型
	type Item;
	// `map` 関数の定義 (`Map` は写像後の新しいイテレータ)
	fn map<T,F>(self, f: F) -> Map<Self, F>
		where F: FnMut(Self::Item) -> T;
	// `filter` 関数の定義 (`Filter` は取捨選択後の新しいイテレータ)
	fn filter<T,F>(self, f: F) -> Filter<Self, F>
		where F: FnMut(&Self::Item) -> bool;
	// `filter_map` 関数の定義 (`FilterMap` は写像+取捨選択後の新しいイテレータ)
	fn filter_map<T,F>(self, f: F) -> FilterMap<Self, F>
		where F: FnMut(Self::Item) -> Option<T>;
}
```

実例は以下の通り

```rust
let num_list: Vec<u8> = vec![3,4,5,7];

let odd_squared_num_list: Vec<u8> =
	num_list.into_iter()
	.filter_map(|num| {
		// 奇数だけ使う
		if num % 2 === 1 { Some( num*num ) }
		else None
	})
	.collect::<Vec<u8>>();
```

上記の例だと `filter_map` に与えたクロージャが特にエラーになることはないが、場合によってはクロージャ内でエラーを発生させうる処理をしたいこともある。要素ごとに順番に `filter_map` のクロージャを呼び出して、どこかでエラーが発生したら、その時点で終了するようにしたい。
以下ではこれを実現する方法を説明する。

## 2つのアプローチ

エラーハンドリング付きの `filter_map` を挟む方法は自分が知る限り2種類存在している。

### 標準ライブラリを使う方法

Rust 標準ライブラリだけでこのような操作はできる。

```rust
let num_list: Vec<u8> = vec![0,3,4,5,7];

let odd_squared_num_list: Vec<u8> =
	num_list.into_iter()
	.filter_map(|num| {
		// 0 の場合はエラーにする
		if num == 0 { return Some(Err("エラー内容")) }

		// 奇数だけ使う
		if num % 2 == 1 { Some(Ok( num*num )) }
		else { None }
	})
	.collect::<Result<Vec<u8>,_>>()?;
```

先ほどの例との違いは
* クロージャの戻り値の型が `Option<T>` から `Option<Result<T,E>>` に変わる
* `collect()` で消費したイテレータを集める先が単なる `Vec<T>` から `Result<Vec<T>,E>` に変わる
* `?` で `Result<Vec<T>,E>` のエラーを外に伝播させることで、依然として `Vec<T>` が返される (オプション)

#### 詳細

[`.collect()`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.collect) は次のように定義されている。
```rust
impl Iterator {
	type Item;
	fn collect<C>(self) -> C
		where C: FromIterator<Self::Item>;
}
```
つまり `C` が [`FromIterator<T>`](https://doc.rust-lang.org/stable/std/iter/trait.FromIterator.html) トレイトを実装している場合に限って実行できる。

通常の `.collect::<Vec<T>>()` ができるのは次のように [`Vec<T>` に対して `FromIterator<T>` が実装されている](https://doc.rust-lang.org/stable/std/iter/trait.FromIterator.html#impl-FromIterator%3CT%3E-for-Vec%3CT%3E)からである。
```rust
impl<T> FromIterator<T> for Vec<T>
```

同様にして [`Result` に対しても `FromIterator<T>` が実装されている](https://doc.rust-lang.org/stable/std/iter/trait.FromIterator.html#impl-FromIterator%3CResult%3CA,+E%3E%3E-for-Result%3CV,+E%3E)。
```rust
impl<T,E,C> FromIterator<Result<T,E>> for Result<C,E>
	where C: FromIterator<T>
```

つまり、既に `FromIterator<T>` が実装されているコレクション型 `C` であれば `Result<T,E>` のイテレータを消費して `Result<C,E>` を作ることができる。 `C` として `Vec<T>` を選んだのが今回の例である。これはイテレート中に `Err` の要素があれば全体も `Err` で終了するようだ。

### `fallible-iterator` を使う方法

エラーが発生しうるイテレータを扱うための [`fallible-iterator`](https://crates.io/crates/fallible-iterator) というクレートが存在する。ここでは [`FallibleIterator`](https://docs.rs/fallible-iterator/0.3.0/fallible_iterator/trait.FallibleIterator.html) というイテレータのトレイトが用意されており、通常の [`std::iter::Iterator`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html) トレイトの関数と同様の関数で、クロージャの返値の型が `Result<*,E>` に置き換わっているため、関数内でエラーが発生した場合にそこで終了できるように設計されている。
`FallibleIterator` に含まれる [`filter_map()`](https://docs.rs/fallible-iterator/0.3.0/fallible_iterator/trait.FallibleIterator.html#method.filter_map) を使うようにすれば、次のように実装することができる。

```rust
use fallible_iterator::{ IteratorExt, FallibleIterator };
let num_list: Vec<u8> = vec![0,3,4,5,7];

let odd_squared_num_list: Vec<u8> =
	num_list.into_iter()
	// `Iterator` を `FallibleIterator` に変換
	.map(|num| Ok(num) ).transpose_into_fallible()
	.filter_map(|num| {
		// 0 の場合はエラーにする
		if num == 0 { Err("エラー内容")?; }

		Ok(
			// 奇数だけ使う
			if num % 2 == 1 { Some( num*num ) }
			else { None }
		)
	})
	.collect::<Vec<u8>>()?;
```

[`.collect()`](https://docs.rs/fallible-iterator/0.3.0/fallible_iterator/trait.FallibleIterator.html#method.collect) の型注釈は、 `Result<Vec<u8>,_>` などとせず、単純にエラーでない場合のコレクション型である `Vec<u8>` を記すだけで `Result` 型の値を返す。

#### 詳細

[`.filter_map()`](https://docs.rs/fallible-iterator/0.3.0/fallible_iterator/trait.FallibleIterator.html#method.filter_map) の前に `.map().transpose_into_fallible()` を挟んでいる。これは `Iterator<Item=u8>` を `FallibleIterator<Item=u8,Error=??>` に変換している。
[`.transpose_into_fallible()`](https://docs.rs/fallible-iterator/0.3.0/fallible_iterator/trait.IteratorExt.html#tymethod.transpose_into_fallible) は `Iterator<Item=Result<T,E>>` を満たす型を `FallibleIterator<Item=T,Error=E>` を満たす型に変換する。
```rust
trait IteratorExt {
	// `Convert` は `FallibleIterator` を満たす型
	fn transpose_into_fallible<T,E>(self) -> Convert<Self>;
		where Self: Iterator<Item=Result<T,E>>;
}
```
つまり予め `Result<T,E>` 型の要素を持つ `Iterator` を準備しなくてはならず、そのために `.map(|num| Ok(num) )` を挟んで `T` を `Result<T,??>` に変換している。

しかし、 `Ok(num)` とするだけでは `Result<T,E>` のエラー型 `E` を決めることはできず、 `.transpose_into_fallible()` を経た後も `FallibleIterator` でのエラー型は不定である。この後に続く `.filter_map()` により初めて実際のエラー型が決まる。 (或いは `.map()` のクロージャの返値の型を明示的に示してもよい)

次に `.filter_map()` について。 `Iterator` の `.filter_map()` ではそれ自身に `Result` 型を処理する方法は備わっていない一方で、 `FallibleIterator` の `.filter_map()` では `Result` 型を返さなくてはならない。
```rust
trait FallibleIterator {
	// イテレートする内容の型
	type Item;
	// エラーが発生した場合のエラー内容の型
	type Error;
	fn filter_map<T,F>(self, f: F) -> FilterMap<Self, F>
		where F: FnMut(Self::Item) -> Result<Option<T>,Self::Error>;
}
```

## 2つの方法を比較

以上2つの方法を比較した。これら2つの違いはざっくりとこのような感じである。
* 依存クレートの有無
* `.map().transpose_into_fallible()` の有無
* `.filter_map()` に与えるクロージャの返値の型の違い

依存クレートがあることや、 `FallibleIterator` に変換するために1行挟む必要があり、しかもエラー型が不定形になることを踏まえると、 `fallible-iterator` の使い勝手は悪そうな気がするが、3つ目を踏まえるとそうとも言えなくなると感じている。

どちらの方法でもクロージャの返値は `Result` と `Option` が絡んだ型になっているのだが、その包含順が2つの方法で逆転している。

| | |
|--:|:--:|
| 標準ライブラリの方法 | `Option<Result<T,E>>` |
| `fallible-iterator` の方法 | `Result<Option<T>,E>` |

どちらでも、値を返す場合、 `None` を返す場合、エラーを返す場合の3種類のケースがあることには変わりないが、 `Result` が外側にある方が使い勝手が良い。
`filter_map` を使っている以上、 `Some` と `None` が現れるのは自然であり、そこに新たに写像や取捨選択とは関係のないエラーのケースを付け加えるのだから、 `Some` や `None` と独立して扱われるべきだと考えられるからだ。
また、 `None` やエラーは包含の外側だと `?` 演算子で簡単に early return ができ、特に `Result` 型を返す関数をクロージャ中で呼び出している場合など、内側で発生したエラーを、その詳細に触れずに一気にクロージャの外側に持ってこれるため、シンプルな表記になりやすい。

...ということで、どちらの方法も一長一短であることが分かった。

## 標準ライブラリの方法で `Result` と `Option` を入れ替えられるか

以上から、標準の `std::iter::Iterator` に対してクロージャが `Result<Option<T>,E>` が返せるような `filter_map` が存在すれば一番幸せになれると考えられる。

ということで、 `filter_map` の代わりに `Result<Option<T>,E>` 型を返せるようにした `filter_map_swapped` 関数を `Iterator` に生やすことにした。
以下にそのためのトレイトの実装例を示す。

```rust
use std::iter::Iterator;

// `Iterator` を拡張するトレイトの定義
pub trait FilterMapSwappedExt: Iterator {
	// `T`: `filter_map_swapped` した後の要素の型
	// `E`: 発生しうるエラーの型
	// `F`: `Result<Option<T>,E>` を返すクロージャ型
	fn filter_map_swapped<T,E,F>(self, f: F)
		-> impl Iterator<Item = Result<T,E>>
	where
		Self: Sized,
		F: FnMut(Self::Item) -> Result<Option<T>,E>;
}

// トレイトの実装
impl<I: Iterator> FilterMapSwappedExt for I {
	fn filter_map_swapped<T,E,F>(self, mut f: F)
		-> impl Iterator<Item = Result<T,E>>
	where
		Self: Sized,
		F: FnMut(Self::Item) -> Result<Option<T>,E>
	{
		// 通常通り `filter_map` を呼び出し、この場限りのクロージャ型を渡している
		// このクロージャに `filter_map_swapped` の引数のクロージャ `f` をムーブしている
		self.filter_map(move |x| {
			// `f` を呼び出して `Result<Option<T>,E>` を受け取り、 `Option<Result<T,E>>` に読み替えている
			match f(x) {
				Ok(Some(y)) => Some(Ok(y)),
				Ok(None) => None,
				Err(y) => Some(Err(y))
			}
		})
	}
}
```

結局のところ通常の `filter_map` を呼び出していることには変わりなく、最後に `Result<Option<T>,E>` を `Option<Result<T,E>>` に読み替える作業を追加しただけである。

大元の `filter_map` 関数の型定義になるべく合わせるようにしている。
`filter_map` 関数の返す型は、元のイテレータ `I` と、引数で与えられるクロージャの型 `F` を使って `FilterMap<I,F>` と表される。
`filter_map_swapped` でも `FilterMap<I,F2>` を返しているのだが、この `F2` (≠ `F`) に相当する型は `filter_map` と違って関数実装内部で定義されるクロージャの型であるから、関数の型定義で示すことはできない。
なので `filter_map_swapped` の返値の型は `FilterMap` などと具体的に示さずに、 `impl Iterator<Item=Result<T,E>>` とトレイトによって示している。

### オマケ: `collect` もちょっと楽をする

`.collect::<Result<Vec<_>,_>()` も書くのが億劫なので、ちょっとは楽をしたい。ということで `FallibleIterator` の `collect` と同様に型パラメータ `C` を受け取って `Result<C,E>` を返す関数を生やしてみる。

```rust
use std::iter::{ Iterator, FromIterator };

pub trait CollectExt<T,E>: Iterator<Item=Result<T,E>> {
	fn collect_res<C>(self) -> Result<C,E>
		where C: FromIterator<T>;
}

impl<I,T,E> CollectExt<T,E> for I
	where I: Iterator<Item=Result<T,E>>
{
	fn collect_res<C>(self) -> Result<C,E>
		where C: FromIterator<T>
	{ self.collect() }
}
```

ということで実装はできたものの、これにより減る労力はどれほどのものだろうか...