rustのiteratorのメモ

まずは、空のtypeと付随するiteratorを作ってみる

```rust
struct A {}
struct AIter {
    now: usize,
}
impl A {
    fn new() -> A {
        A {}
    }

    fn iter(&self) -> AIter {
        AIter { now: 0 }
    }
}

impl Iterator for AIter {
    type Item = usize;
    fn next(&mut self) -> Option<usize> {
        self.now += 1;
        Some(self.now - 1)
    }
}

fn main() {
    let a = A::new();
    assert_eq!(
        vec![0, 1, 2, 3, 4],
        a.iter().take(5).collect::<Vec<usize>>()
    );
}
```
[playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=ce77e1840b06640a2306cac41fea52e5)
特につまるところはなし。iterの引数には&つけないと、iter()よぶとmoveされてしまう。

次にAにVec<i32>を足してその値をiteratorでとりだせるようにしてみる

```rust
struct A {
    v: Vec<i32>,
}
struct AIter<'a> {
    a: &'a A,
    now: usize,
}
impl A {
    fn new(v: Vec<i32>) -> A {
        A { v: v }
    }

    fn iter(&self) -> AIter {
        AIter { a: &self, now: 0 }
    }
}

impl<'a> Iterator for AIter<'a> {
    type Item = i32;
    fn next(&mut self) -> Option<i32> {
        self.now += 1;
        if self.now - 1 < self.a.v.len() {
            Some(self.a.v[self.now - 1])
        } else {
            None
        }
    }
}

fn main() {
    let a = A::new(vec![6, 7, 8, 9, 10, 11, 12]);
    assert_eq!(vec![6, 7, 8, 9, 10], a.iter().take(5).collect::<Vec<i32>>());
}
```
[playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9c4a120923d08815c6e02d21739c48bb)
Iteratorの中にreferenceをもたせてその値を使用する。

もう少しややこしくして、`Vec<String>`にしつつ、`&str`をiteratorでとりだせるようにする。

```rust
struct A {
    v: Vec<String>,
}
struct AIter<'a> {
    a: &'a A,
    now: usize,
}
impl A {
    fn new(v: Vec<&str>) -> A {
        A {
            v: v.iter().map(|s| s.to_string()).collect(),
        }
    }

    fn iter(&self) -> AIter {
        AIter { a: &self, now: 0 }
    }
}

impl<'a> Iterator for AIter<'a> {
    type Item = &'a str;
    fn next(&mut self) -> Option<&'a str> {
        self.now += 1;
        if self.now - 1 < self.a.v.len() {
            Some(&self.a.v[self.now - 1])
        } else {
            None
        }
    }
}

fn main() {
    let a = A::new(vec!["a", "b", "c", "d", "e", "f", "g"]);
    assert_eq!(
        vec!["a", "b", "c", "d", "e"],
        a.iter().take(5).collect::<Vec<&str>>()
    );

}
```
[playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=3cb91c5dcf91cb544b183db68dcb79d4)
`Vec<i32>`を`Vec<String>`にして`Option<i32>`を`Option<&str>`にする
Stringと&strのあたりはあまり自信なし

ここからが本題。2種類のIteratorをつくってtake(5)を関数にしてみる

```rust
struct A {
    v: Vec<String>,
}
struct AIter<'a> {
    a: &'a A,
    now: usize,
}
struct AIter2 {
    now: usize,
}
impl A {
    fn new(v: Vec<&str>) -> A {
        A {
            v: v.iter().map(|s| s.to_string()).collect(),
        }
    }

    fn iter(&self) -> AIter {
        AIter { a: &self, now: 0 }
    }
    fn iter2(&self) -> AIter2 {
        AIter2 { now: 0 }
    }
}

impl<'a> Iterator for AIter<'a> {
    type Item = &'a str;
    fn next(&mut self) -> Option<&'a str> {
        self.now += 1;
        if self.now - 1 < self.a.v.len() {
            Some(&self.a.v[self.now - 1])
        } else {
            None
        }
    }
}
impl Iterator for AIter2 {
    type Item = usize;
    fn next(&mut self) -> Option<usize> {
        self.now += 1;
        Some(self.now - 1)
    }
}

fn take5<T, I : Iterator<Item = T>>(iter: I) -> Vec<T> {
    iter.take(5).collect()
}

//fn take5<T>(iter: impl Iterator<Item = T>) -> Vec<T> {
//    iter.take(5).collect()
//}

fn main() {
    let a = A::new(vec!["a", "b", "c", "d", "e", "f", "g"]);
    assert_eq!(vec!["a", "b", "c", "d", "e"], take5(a.iter()));
    assert_eq!(vec![0, 1, 2, 3, 4], take5(a.iter2()));
}
```
[playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=fc50cc9c02b871b3704ebb5b919968e9)
generics<strike>とimpl Trait</strike>をつかう。<strike>impl Traitがない時代はどうしてたのかは不明。</strike>こういう場合には、IntoIteratorは使えない。
impl Traitを使う必要はない。

assert_eq!はやめて、take5の中でforでprintln!するようにしてみる。以下は抜粋

```rust
fn take5<T: std::fmt::Display>(iter: impl Iterator<Item = T>) {
    for i in iter.take(5) {
        println!("{}", i);
    }
}

fn main() {
    let a = A::new(vec!["a", "b", "c", "d", "e", "f", "g"]);
    take5(a.iter());
    take5(a.iter2());
}
```
[playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=76ce7ad306e2427f8547c34feb096edb)