Rustで複雑な複合型をイテレートする

# はじめに
Rustで`(A, B, Option<C>, Vec<D>)`のような複雑な複合型をイテレートする方法を考えます。すなわち

```rust
let x = (A {}, B {}, Some(C {}), vec![D {}, D {}]);
for y in x {
    println!("{:?}", y); // A B C D D と表示したい
}         
```

こういうことをしたい、ということですね。
簡単にできるわけではないですが、いろいろと下準備をすると実現可能です。

# イテレータの返す型
当然ですがイテレータは一つの型しか返せません。今返したい型は`A,B,C,D`の4つあるので、それらをまとめた型が必要です。

```rust
#[derive(Debug)]
struct A;
#[derive(Debug)]
struct B;
#[derive(Debug)]
struct C;
#[derive(Debug)]
struct D;

#[derive(Debug)]
enum Any<'a> {
    A(&'a A),
    B(&'a B),
    C(&'a C),
    D(&'a D),
}
```

ここでは4つをまとめる型として`Any`を作りました。
`#[derive(Debug)]`は最後に`println!`するためにつけただけで、本題とは無関係です。

# Anyを返すイテレータ

次にイテレータを表す型`Iter`を作ります。この型はメンバとしてイテレートすべき`Any`のリストを持っています。単に`list: Vec<Any<'a>>`とせず、`Anys`を定義した理由は後程説明します。

```rust
struct Anys<'a>(Vec<Any<'a>>);

struct Iter<'a> {
    list: Anys<'a>,
}
```

この`Iter`に対してIteratorトレイトを実装します。
実装としては単にリストの中身を`pop()`で取り出していくだけです。

```rust
impl<'a> Iterator for Iter<'a> {
    type Item = Any<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        self.list.0.pop()
    }
}
```

# イテレータを作る

先ほど定義したイテレータを、冒頭の複合型から作る方法を考えます。まず、単に型`A`の場合は簡単です。

```rust
impl<'a> From<&'a A> for Anys<'a> {
    fn from(x: &'a A) -> Self {
        Anys(vec![Any::A(x)])
    }
}
```

このようなFromトレイトを実装すれば`A`から`Anys`を作れます。さらに

```rust
impl<'a> IntoIterator for Anys<'a> {
    type Item = Any<'a>;
    type IntoIter = Iter<'a>;

    fn into_iter(mut self) -> Self::IntoIter {
        self.0.reverse();
        Iter { list: self }
    }
}
```

`Anys`に対してIntoIteratorトレイトを実装すれば、`Anys`を介して`A`をイテレートすることができます。つまり

```rust
let x = A {};
let x: Anys = (&x).into();
for y in x {
    println!("{:?}", y);
}
```

こういうことができるようになりました。
`A`に対してもIntoIteratorトレイトを実装すれば途中の`let x: Anys = (&x).into();`も不要になりますが、ここでは省略しています。

# 複合型への対応

あとはFromトレイトを増やしていくだけです。`B,C,D`から`Anys`へのFromトレイトは`A`と同じなので省略します。
`Vec`と`Option`、タプルを同様に定義します。

```rust
impl<'a, T: 'a> From<&'a Vec<T>> for Anys<'a>
where
    &'a T: Into<Anys<'a>>,
{
    fn from(x: &'a Vec<T>) -> Self {
        let mut ret = Vec::new();
        for x in x {
            ret.append(&mut x.into().0);
        }
        Anys(ret)
    }
}
```

これは`Vec`の場合です。型制約`&'a T: Into<Anys<'a>>`を付けているので、`Vec`の中身が`Anys`へ変換可能な任意の`Vec`をこれで変換できます。
`Option`とタプルも同様です。

```rust
impl<'a, T: 'a> From<&'a Option<T>> for Anys<'a>
where
    &'a T: Into<Anys<'a>>,
{
    fn from(x: &'a Option<T>) -> Self {
        let mut ret = Vec::new();
        if let Some(x) = x {
            ret.append(&mut x.into().0);
        }
        Anys(ret)
    }
}

impl<'a, T0: 'a, T1: 'a, T2: 'a, T3: 'a> From<&'a (T0, T1, T2, T3)> for Anys<'a>
where
    &'a T0: Into<Anys<'a>>,
    &'a T1: Into<Anys<'a>>,
    &'a T2: Into<Anys<'a>>,
    &'a T3: Into<Anys<'a>>,
{
    fn from(x: &'a (T0, T1, T2, T3)) -> Self {
        let mut ret = Vec::new();
        let (t0, t1, t2, t3) = x;
        ret.append(&mut t0.into().0);
        ret.append(&mut t1.into().0);
        ret.append(&mut t2.into().0);
        ret.append(&mut t3.into().0);
        Anys(ret)
    }
}
```

これで、`Vec`と`Option`と`A,B,C,D`をタプルで組み合わせた任意の複合型を`Anys`に変換できるようになりました。
（ここでは4つのタプルしか定義していませんが、それ以外の個数も同様なので必要なだけ増やせばよいです）

また、`Vec<Any<'a>>`の代わりに`Anys`を定義したのはこのFromトレイトを実装するためです。Rustではあるトレイトを実装する際に「そのトレイトを定義したクレートか、対象の型を定義したクレートでしか実装できない」という制限があります。Fromトレイトも`Vec`もこのクレートで定義したものではないので、`Vec`のままだとFromトレイトは実装できません。しかし、`Anys`はこのクレートで定義した型なのでFromトレイトを実装できます。

# まとめ

最終的にこういうことができるようになりました。

```rust
fn main() {
    let x = (A {}, B {}, Some(C {}), vec![D {}, D {}]);
    let x: Anys = (&x).into();
    for y in x {
        println!("{:?}", y);
    }

    let x = (Some(D {}), C {}, vec![B {}, B {}, B {}], Some(A {}));
    let x: Anys = (&x).into();
    for y in x {
        println!("{:?}", y);
    }
}
```