D 2.067.0 の新機能（イテレーション篇）

先日 D 2.067.0 がリリースされたものの、現時点で [change log](http://dlang.org/changelog.html#new2_067.0) が残念なので、イテレーション関連の機能のうち個人的に気になるものをちょっとだけ紹介してみます。
他の新機能については誰かが紹介してくれるはず。

# 導入
今リリースにおける新機能のうち、次に挙げるイテレーション関係のものを紹介します。

* [`std.algorithm.iteration.each`](http://dlang.org/phobos/std_algorithm_iteration.html#.each)
* [`std.concurrency.Generator`](http://dlang.org/phobos/std_concurrency.html#.Generator)
* [`std.range.enumerate`](http://dlang.org/phobos/std_range.html#.enumerate)
* [`std.range.tee`](http://dlang.org/phobos/std_range.html#.tee)

補足ですが、今リリースから `std.algorithm` や `std.range` といった巨大なモジュールがパッケージ化されましたが、子モジュールだけ `import` することも、今までどおり親モジュールの名前で一括 `import` することも可能です。

* [dlang - D言語 Language Update 2013 - Qiita](http://qiita.com/repeatedly/items/643a43b6407732f096e1#3-2)

## 何をどうするの
レンジを UFCS でチェインしたワンライナーをよしとする宗派を信仰している関係で、サンプルコードが妙です。次のページが教義をよく説明していると思われますので、目を通しておくとよいでしょう。

* [D言語のUFCSを使い倒す - codelogy](http://www.codelogy.org/entry/2012/07/13/110718)

上記にある例を参考に、以後の比較で使う D 2.066.1 までのコードを書いてみると、次のようになります。

```d:example.d
void main(){
    import std.stdio, std.algorithm, std.range;

    5.iota.map!(a => (a.writeln, 0)).array;  // <---
}
```

期待される出力は次のとおりです。

```console:output
0
1
2
3
4
```

余計な括弧は除去していますが、だいぶ無駄があります。これを書き換えるがために使えそうな新機能を選んだというだけです。

# 例示
## [`std.algorithm.iteration.each`](http://dlang.org/phobos/std_algorithm_iteration.html#.each)
`foreach` の式バージョンみたいな関数です。最初の例を微改造すると次のようになります。

```d
5.iota.map!(a => (a.writeln, 0)).each;
```

`array` が `each` になっただけですが、無駄に配列を作らずにループを回す感覚で副作用を起こせるので有用です。戻り値がないことに注意してください。
また、`each` にはテンプレート引数を与えることができます。

```d
5.iota.each!writeln;

```

`map` を消せました。`map` に渡す関数は戻り値がなければならないこと、ラムダ構文を使いたいがゆえにカンマ演算子を使っていますが、カンマ演算子を廃止しようという議論があって（うやむやになったけど）震えていたところ、無事に導入された優れものです。
また、テンプレート引数にはラムダを渡すこともできます。

```d
5.iota.each!(a => a.writeln);
```

この `each` は以後の例で多用します。

## [`std.concurrency.Generator`](http://dlang.org/phobos/std_concurrency.html#.Generator)
ジェネレータです。クラスです。ループを入力レンジに変換できるので有用です。引数を取らずに、内部で `yield` を呼び出すようにした関数をコンストラクタに渡します。

```d
new Generator!int({foreach(i; 0..5) i.yield;}).each!writeln;
```

`nextPermutation` のレンジ化にも有用です。
無駄に `Generator` を使いたければ次のように書けます。

```d
new Generator!int(() => 5.iota.each!yield).each!writeln;
```

注意点としては、所属するモジュールの性質上コンパイル時処理できません。

```d
enum a = new Generator!int(() => 5.iota.each!yield).array;  // bad
```

そもそも、モジュール的に、今回の例のような用途では役不足（誤用じゃない）かもしれません。本来の用途など、[詳しいことは repeatedly の人が説明してくれるはずです](http://qiita.com/repeatedly/items/9f8caba690930c9a4b8a#%E3%81%BE%E3%81%A8%E3%82%81)。

## [`std.range.enumerate`](http://dlang.org/phobos/std_range.html#.enumerate)
入力レンジをインデックス付きのレンジにする関数です。`foreach` にインデックス付きで渡したいときに特に有用です。`lockstep` や `zip` で頑張っていた処理が楽に書けるようになるかもしれません。
今回の例で無理矢理使うとすれば次のようになります。

```d
false.repeat(5).enumerate.each!(a => a[0].writeln);
```

`front` するとインデックスと要素のタプルが返されますが、要素はどうでもよく、インデックスを出力したいという観点で `false.repeat(5)` という無駄な書き方をしてみました。
また、`enumerate` には開始インデックスを引数として渡すこともできます。

## [`std.range.tee`](http://dlang.org/phobos/std_range.html#.tee)
レンジ処理のチェインの間に挟んで、その値を覗く関数です。T 字形の何かです。チェインの前後で値を変えたくない場合に有用です。リファレンスにサンプルコードがないので、ソースファイルの `unittest` を読んでください。闇を感じます。
普通に使う分には簡単です。

```d
5.iota.tee!writeln.each;
```

`pipeOnPop` というテンプレート引数が闇です。リファレンスの補足がてら、説明します。

```d
3.iota.tee!(a => writeln("a ", a)).map!"a+10".tee!(a => writeln("b ", a)).each!(a => writeln("c ", a));
writeln;
3.iota.tee!(a => writeln("a ", a), No.pipeOnPop).map!"a+10".tee!(a => writeln("b ", a)).each!(a => writeln("c ", a));
writeln;
3.iota.tee!(a => writeln("a ", a), No.pipeOnPop).map!"a+10".tee!(a => writeln("b ", a), No.pipeOnPop).each!(a => writeln("c ", a));
writeln;
3.iota.tee!(a => writeln("a ", a)).map!"a+10".tee!(a => writeln("b ", a), No.pipeOnPop).each!(a => writeln("c ", a));
```
いつ覗くかというパラメータです。このチェインを、`iota` から右に進み、`each` に達してから再び `iota` に向けて左に戻ると見れば、`No.pipeOnPop` では行きで覗き、`Yes.pipeOnPop` では帰りで、ということでしょう。個人的には、DOM のイベントのキャプチャフェイズ、バブリングフェイズのイメージですが、普通に、スタックの push/pop やネストしたループの入口、出口のイメージのほうがわかりやすいかもしれません。
いずれにしろ、出力結果は次のようになるでしょう。

```console:output
c 10
b 10
a 0
c 11
b 11
a 1
c 12
b 12
a 2

a 0
c 10
b 10
a 1
c 11
b 11
a 2
c 12
b 12

a 0
b 10
c 10
a 1
b 11
c 11
a 2
b 12
c 12

b 10
c 10
a 0
b 11
c 11
a 1
b 12
c 12
a 2
```

呼び出しのタイミングがそれぞれ異なることがわかります。

# 締め
DMD のリリースプロセス改革が始まりつつあり、その先陣を切るリリースであるがゆえか、冒頭に書いたように表沙汰になっていない変更点はまだまだあるはずです。今回紹介できなかった分は誰かに任せます。