PHP入門 ジェネレーター
ジェネレーター(Generator)の見た目は、普通の関数です。しかし、普通の関数がreturn命令で値を返したらそれで終わりであるのに対して、ジェネレーターはyieldという命令を利用することで、つど、その時々の値を返すせる点が異なります。
<?php
function myGen(){
yield 'あいうえお';
yield 'かきくけこ';
yield 'さしすせそ';
}
foreach(myGen() as $value){
print $value.'<br />';
}
yieldは、returnとよく似た命令で、関数の値を呼び出し元に返します。しかし、return命令がその場で関数の実行を終了するのに対して、yield命令は処理を一定停止します。つまり、次に呼び出されたときには、その時点から処理を再開できます。よって、定義されたジェネレーターmyGenをforeach命令に渡すことで、ループのつど、先頭から順番にyield命令による値が返されます。
ジェネレーターの結果を取得する
ジェネレーター関数でもreturn命令は利用できます。その場合、return命令はジェネレーターの最終的な結果を表します。return命令によってジェネレーターは終了するので、一般的にreturn命令を呼び出すのは、ジェネレーターがすべての処理を終えたタイミングです(❶)。return命令で返された値を取得するには、GeneratorオブジェクトのgetReturnメソッドを利用します(❷)。
<?php
function readLines(string $path){
//行数
$i = 0;
$file = fopen($path, 'rb') or die('ファイルが見つかりません');
//行単位にテキストを取得&yield
while($line = fgets($file, 1024)){
$i++;
yield $line;
}
fclose($file);
//読み込んだテキストの行数を返す
return $i; //➊
}
$gen = readLines('sample.dat');
foreach($gen as $line){
print $line.'<br />';
}
print "{$gen->getReturn()}行ありました" //➋
一部の処理を他のジェネレーターに委譲する
yield from命令を利用することで、ジェネレーターの中で別のジェネレーター、または配列を呼び出し、これを列挙できます。すべての値を列挙できたら、改めて後続のyield命令を続行するのです。
構文:yield from関数
yield from list
list | 他のジェネレーター、配列など |
例:readFiles関数は、指定されたファイル(配列)から順にテキストを取り出していくためのジェネレーターです。この際、readFiles関数は、もう1つのジェネレーターに処理を委ねます。
<?php
function readFiles(string ...$files){
//配列から順にファイルパスを取り出す
foreach($files as $file){
//ジェネレーターreadLinesに処理を委ねる
yield from readLines($file);
}
}
function readLines(string $path){
$file = fopen($path, 'rb') or die('ファイルが見つかりません');
//行単にテキストを取得
while($line = fgets($file, 1024)){
yield $line;
}
fclose($file);
}
//sample.dat/sample2.datの内容を順に列挙
foreach(readFiles('sample.dat', 'sample2.dat') as $line){
print $line.'<br />';
}