#ジェネレータ関数とは
ジェネレータ関数は一度だけ値をreturnするのではなく、必要に応じて何度でも「yield(産出)」することができる関数のこと。
ジェネレータ関数が呼ばれると、反復処理が可能なオブジェクトを返す。
反復処理をするためにforeachなどと一緒に使用され、値が必要になるたびに PHP がジェネレータ関数を呼び出す。
そして、ジェネレータが値をyieldした時点の状態を保存しておき、 次に値が必要になったときにはそこから再開できるようにする。
#yieldとは
ジェネレータ関数を使用するためのキーワードが**「yield」**。
yieldを実行すると、ジェネレーターを生成し現在の処理を中断したまま保持する事が出来る。
以下PHPマニュアルより抜粋
<?php
function gen_one_to_three() {
for ($i = 1; $i <= 3; $i++) {
// yield を繰り返す間、$i の値が維持されることに注目しましょう
yield $i;
}
}
$generator = gen_one_to_three();
foreach ($generator as $value) {
echo "$value\n";
}
?>
出力結果
1
2
3
ジェネレータは、呼び出されると最初のyield文までを実行して、yield文によって呼び出し元に値を返している。
その際PHPは、実行されたyield文の位置を保存しておき、次にそのジェネレータが呼び出されたときに、そのyield文の次の行から実行を再開している。
#ジェネレータの何が良いか
- イテレータが簡潔に書ける
- 不必要なメモリを使用しなくて済む
##具体例
1~10000までを出力する
###ジェネレータを使用しない
foreach (range(1, 10000) as $val) {
echo $val;
}
この場合、1万要素分のメモリが確保される。
###ジェネレータを使用する
function countNum($limit) {
for ($i = 1; $i <= $limit; ++$i) {
yield $i;
}
}
foreach (countNum(10000) as $val) {
echo $val;
}
値をジェネレータから取得しているので、1万要素分のメモリが確保されない。