[RustDoc翻訳] 4.5. Iterators

動機: Rustについて学ぶと共に英語の翻訳をしてみよう思った(読むのは興味をもった順ですので悪しからず)
誤訳や改善案等、見つけた場合はご指摘の程宜しくお願いします。

* 元記事 : https://doc.rust-lang.org/book/iterators.html
* ライセンス : MIT license, Apache License 2.0.
    - See [LICENSE-APACHE](https://github.com/rust-lang/rust/blob/1.2.0/LICENSE-APACHE), [LICENSE-MIT](https://github.com/rust-lang/rust/blob/1.2.0/LICENSE-MIT), and [COPYRIGHT](https://github.com/rust-lang/rust/blob/1.2.0/COPYRIGHT) for details.

---

# イテレータ

ループの話をしましょう。

Rustの`for`ループを覚えていますか？こちらが例になります。

```rust
for x in 0..10 {
    println!("{}", x);
}
```

今やあなたはRustに詳しいですから、私達はどのようにこの文が動いているのか詳しく話せます。
レンジ(ここでは`0..10`)は'イテレータ'です。イテレータは`.next()`メソッドを繰り返し呼び出すことができ、その都度順番に値を返すものです。こんな風に書いてみます。

```rust
let mut range = 0..10;

loop {
    match range.next() {
        Some(x) => {
            println!("{}", x);
        },
        None => { break }
    }
}
```

変数rangeにイテレータをミュータブル束縛しています。`loop`の中の`match`は、イテレータである`range.next()`を呼び出すことで返ってくる次の値への参照を使用しています。`next`には`Option<i32>`が返ってきます。このケースでは、イテレータの次の値が返ってくればその値は`Some(i32)`であり、返ってくる値が無くなれば`None`が返ってきます。もし`Some(i32)`であればそれを表示し、`None`であれば`break`によりループから脱出しています。

このコードは、基本的に`for`ループバージョンと同じ動作です。`for`ループはこの`loop`/`match`/`break`で構成された処理を手軽に書ける方法というわけです。

しかしながら、`for`ループはイテレータのみに使うものではありません。`Iterator`トレイトを実装し組み込むことで、あなた自作のイテレータを書くこともできます。このガイドの範囲外ですが、Rustは多様な反復処理を実現するために便利なイテレータを幾つか提供しています。ただ、それらについて話す前に、Rustのアンチパターンについて話しておかなければなりません。しかもアンチパターンというのは、先ほど書いたようにレンジを使うことなのです。

ええ、確かに私たちはたった今レンジが如何にクールなのか話しました。しかしレンジは古典的過ぎます。例えば、もしあなたがvectorの中身を繰り返し処理したいとき、こんな風に書きたくなるかもしれません。

```rust
let nums = vec![1, 2, 3];

for i in 0..nums.len() {
    println!("{}", nums[i]);
}
```

これは実際のイテレータの使い方からすれば全く正しくありません。あなたはvectorを直接反復処理できるのですから、こう書くべきです。

```rust
let nums = vec![1, 2, 3];

for num in &nums {
    println!("{}", num);
}
```

これには2つの理由があります。第一に、このほうが書き手の意味するところがはっきり表現できます。私たちはvectorのインデックスを作成してからその要素を繰り返し参照したいのではなく、vector自体を反復処理したいのです。第二に、このバージョンのほうがより効率的です。1つ目の例では`num[i]`というようにインデックスを使っているため、余計な境界チェックが発生します。しかし、イテレータが順番にvectorの各要素の参照を生成していくため、2つ目の例では境界チェックが発生しません。これはイテレータにとってごく一般的な性質です。私たちは不要な境界チェックを取り除いてもなお安全であることが分かっていますから、より効率的な2つ目の例を使うべきです。

ここにはもう1つ、`println!`の動作という詳細が100%はっきりしていない処理があります。`num`は実際には`&i32`型です。これは`i32`の参照であり、`i32`それ自体ではありません。`println!`は私たちがそのことを理解していなくとも、参照からうまく値を取り出してくれます。このコードも正しく動作します。

```rust
let nums = vec![1, 2, 3];

for num in &nums {
    println!("{}", *num);
}
```

今、私たちは明示的に`num`から参照を取り出しました。なぜ`&nums`は私たちに参照を渡すのでしょうか？第一に、`&`を用いて私たちが明示的に要求したからです。第二に、もしデータそれ自体を私たちに渡す場合、私たちはデータの所有者でなければならないため、データの複製と、それを私たちに渡す操作が伴います。参照を使えば、データの参照を借用し、参照を介するだけで、ムーブを行う必要がなくなります。

そういうわけで、今やレンジはあまりあなたが欲しいものではなくなりました。それではあなたが代わりに欲しいと思うものについて話しましょう。

それは大きく分けてイテレータ、*イテレータアダプタ*、そして*コンシューマ*の3つです。以下が定義となります。

* *イテレータ*はあなたに値の列を渡します。
* *イテレータアダプタ*はイテレータに作用し、出力の異なるイテレータを生成します。
* *コンシューマ*はイテレータに作用し、幾つかの最終的な値の組を返します。

あなたは既にイテレータとレンジを見てきたのですから、最初にコンシューマについて話しましょう。

## コンシューマ

コンシューマとはイテレータに作用し、1種類以上の値を返すものです。最も一般的なコンシューマは`collect()`です。このコードは全くコンパイルできませんが、意図するところは伝わるでしょう。

```{rust,ignore}
let one_to_one_hundred = (1..101).collect();
```

ご覧のとおり、ここでイテレータが`collect()`を呼び出しています。`collect()`はイテレータが渡す沢山の値を受け取り、その結果をコレクションとして返します。それならなぜこのコードはコンパイルできないのでしょうか？Rustはあなたが集めたい値の型を判断することができないため、あなたが知っている型を指定する必要があります。こちらのバージョンはコンパイルできます。

```rust
let one_to_one_hundred = (1..101).collect::<Vec<i32>>();
```

もしあなたが覚えているなら、`::<>`構文で型ヒントを与える事ができ、整数型のvectorが欲しいと伝えることができます。しかし、常に型をまるごとを書く必要はありません。`_`を用いることで部分的に推論してくれます。

```rust
let one_to_one_hundred = (1..101).collect::<Vec<_>>();
```

これは"値を`Vec<T>`の中に集めて下さい、しかし`T`は私のために推論して下さい"という意味です。このため`_`は度々"型プレースホルダー"と呼ばれています。

`collect()`は最も有名なコンシューマですが、他にもあります。`find()`はそのひとつです。

```rust
let greater_than_forty_two = (0..100)
                             .find(|x| *x > 42);

match greater_than_forty_two {
    Some(_) => println!("We got some numbers!"),
    None => println!("No numbers found :("),
}
```

`find`はクロージャを引数にとり、イテレータの各要素の参照に対して処理を行います。ある要素が私たちの期待するものであれば、このクロージャは`true`を返し、そうでなければ`false`を返します。マッチングする要素が無いかもしれないため、`find`は要素それ自体ではなく`Option`を返します。

もう一つの重要なコンシューマは`fold`です。ここでは次のようになります。

```rust
let sum = (1..4).fold(0, |sum, x| sum + x);
```

`fold()`は`fold(base, |accumulator, element| ...)`というシグネチャで、2つの引数を取ります。第1引数は*base*と呼ばれます。第2引数は2つ引数を受け取るクロージャです。クロージャの第1引数は*accumulator*と呼ばれており、第2引数は*element*です。各反復毎にクロージャが呼び出され、その結果が次の反復のaccumulatorの値となります。反復処理の開始時に、baseがaccumulatorの値となります。

ええ、少し混乱しますね。ではこのイテレータを以下の値で試してみましょう。

| base | accumulator | element | クロージャの結果 |
|------|-------------|---------|------------------|
| 0    | 0           | 1       | 1                |
| 0    | 1           | 2       | 3                |
| 0    | 3           | 3       | 6                |

これらの引数で`fold()`を呼び出してみました。

```rust
(1..4).fold(0, |sum, x| sum + x);
```

というわけで、`0`がbaseで、`sum`がaccumulatorで、xがelementです。1度目の反復では、私たちはsumに0をセットし、`nums`の1つ目の要素`1`が`x`になります。私たちはそのとき`sum`と`x`を足し、`0 + 1 = 1`を計算します。2度目の反復では前回の`sum`がaccumulatorになり、elementは値の列の2番目の要素`2`になるため、`3 + 3 = 6`となり、これが最終的な結果となります。`1 + 2 + 3 = 6` が、得られる結果となります。

ふぅ、ようやく説明し終わりました。`fold`は初めのうちこそ少し奇妙に見えるかもしれませんが、一度理解すればあらゆる場面で使えるでしょう。何かのリストを持っていて、そこから1つの結果を求めたいときならいつでも、`fold`は適切な処理です。
イテレータにはまだ話していないもう1つの性質、遅延性があり、コンシューマはそれに関連して重要な役割を担っています。それではもっと詳しくイテレータについて話していきましょう、そうすればなぜコンシューマが重要なのか理解できるはずです。

## イテレータ

前に言ったように、イテレータは`.next()`メソッドを繰り返し呼び出すことができ、その都度順番に値を返すものです。メソッドを繰り返し呼ぶ必要があることから、イテレータは`lazy`であり、前もって全ての値を生成できないことがわかります。例えばこのコードでは、`1-100`の値は実際には生成されておらず、単にその代わりとなる値を生成しています。

```rust
let nums = 1..100;
```

私たちはレンジを使っていないため、レンジは値を生成しません。コンシューマを追加してみましょう。

```rust
let nums = (1..100).collect::<Vec<i32>>();
```

今、`collect()`は幾つかの値を渡してくれるレンジを要求し、値を生成する作業を行います。レンジは基本的な2つのイテレータのうちの1つです。もう片方は`iter()`です。`iter()`はvectorを順番に各要素を渡してくれる単純なイテレータに変換できます。

```rust
let nums = vec![1, 2, 3];

for num in nums.iter() {
   println!("{}", num);
}
```

これら2つの基本的なイテレータはあなたの役に立つはずです。無限を扱えるものも含め、より応用的なイテレータも幾つか用意されています。

これでイテレータについては十分でしょう。私たちがイテレータに関して最後に話しておくべき概念がイテレータアダプタです。それでは説明しましょう！

## イテレータアダプタ

*イテレータアダプタ*はイテレータを受け取って何らかの方法で加工し、新たなイテレータを生成します。`map`はその中でも最も単純なものです。

```{rust,ignore}
(1..100).map(|x| x + 1);
```

`map`は別のイテレータに呼び出され、各要素の参照をクロージャに引数として与えた結果を、新しいイテレータとして生成します。つまりこのコードは私たちに`2-100`の値を返してくれるでしょう。えーっと、厳密には少し違います！もしこの例をコンパイルすると、こんな警告が出るはずです。

```text
warning: unused result which must be used: iterator adaptors are lazy and
         do nothing unless consumed, #[warn(unused_must_use)] on by default
(1..100).map(|x| x + 1);
 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```

また遅延性にぶつかりました！このクロージャは実行されないですね。例えばこれは何の数字も出力されません。

```{rust,ignore}
(1..100).map(|x| println!("{}", x));
```

もし副作用のためにイテレータに対してクロージャの実行を試みるのであれば、代わりに`for`を使いましょう。

興味深いイテレータアダプタは沢山あります。`take(n)`は元のイテレータの`n`回目までを実行するイテレータを返します。これは元のイテレータに対して副作用を及ぼさないことに注意して下さい。では以前言っていた無限のイテレータを試してみましょう。

```rust
#![feature(step_by)]
for i in (1..).step_by(5).take(5) {
    println!("{}", i);
}
```

これの出力は、

```text
1
6
11
16
21
```

`filter()`は引数としてクロージャをとるアダプタです。このクロージャは`true`か`false`を返します。`filter()`が生成する新たなイテレータはそのクロージャが`true`を返した要素のみとなります。

```rust
for i in (1..100).filter(|&x| x % 2 == 0) {
    println!("{}", i);
}
```

これは1から100の間の偶数を全て出力します。(`filter`が反復処理をされている要素を消費[^consume]しないようにするために、述語に各要素の参照が渡される`&x`パターンを使用して整数自体を抽出していることに注意してください)

あなたはここまでに説明された3つの概念を全て繋げることができます。イテレータから始まり、アダプタを幾つか繋ぎ、結果を消費といった感じです。これを見て下さい。

```rust
(1..1000)
    .filter(|&x| x % 2 == 0)
    .filter(|&x| x % 3 == 0)
    .take(5)
    .collect::<Vec<i32>>();
```

これは`6, 12, 18, 24,`そして`30`が入ったvectorがあなたに返されます。

イテレータ、イテレータアダプタ、そしてコンシューマがあなたの助けになることをほんの少しだけ体験できました。本当に便利なイテレータが幾つも用意されていますし、あなたがイテレータを自作することもできます。イテレータは全ての種類のリストに対し効率的な処理方法と安全性を提供します。これらは初めこそ珍しいかもしれませんが、もし使えばあなたは夢中になることでしょう。全てのイテレータとコンシューマのリストは[イテレータモジュールドキュメント](https://doc.rust-lang.org/std/iter/)を参照して下さい。

---

[^consume]:  和訳「消費」 原文 "consume"、コンシューマを適用してイテレータを消費するという意味合い