26
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ジェネレータとyieldについて

Posted at

#ジェネレータ関数とは
ジェネレータ関数は一度だけ値を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万要素分のメモリが確保されない。

26
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?