たにしきんぐダム

プログラミングやったりゲームしてます

PHP でジェネレータを作ったり遅延評価してみる

ジェネレータを作ったり遅延評価するのが流行っているようなので、PHP5.5.0から導入されたジェネレータを使って同様のことをPHPでもやってみようと思いました。

PHPイテレータ、ジェネレータ

PHP 5 は、foreach のような反復処理を可能とするよう オブジェクトを定義する手段を提供しており、IteratorIteratorAggregateなどを実装することによってオブジェクトの反復処理の方法などを細かく指定することができます.

ジェネレータ

先ほど述べたインターフェースを実装することによって反復処理を可能とするオブジェクトを実装することもできますが、ジェネレータを使えば簡単に実装することができます.

早速いくつか簡単なジェネレータを実装してみます。

以上のように内部ではcurrent()メソッドで現在自身が保持している要素を出力し、nextメソッドで次の要素に進むということをしているのですが、同様の処理をforeachで行うことができます.

以下はフィボナッチ数列を無限に返すジェネレータです.

遅延評価

PHP で yield を使ったジェネレータを作成すると遅延評価されていることはこれまでの例から分かることと思います. イテレータを引数にとってイテレータを返す関数を利用することで, より複雑な処理を行うことができます. このようなイテレータを生成する関数はPHP には標準では存在しません. (lstrojny/functional-php · GitHubnikic/iter · GitHubのような外部ライブラリは存在しますが…)
それらの関数を模倣してみます.

実際の例は以下

PHPではデフォルトではリストを受け取ってリストを返すarray_map() やarray_fileter() などは存在しますが、イテレータを受け取ってイテレータを返すようなmap, filter などが存在しないので3~27行目で独自に簡易的に実装しています.