最近、このコードに出会いました:
function xrange($min, $max)
{
for ($i = $min; $i <= $max; $i++) {
yield $i;
}
}
このキーワードは初めて見ましたyield
。コードを実行しようとすると
解析エラー: 構文エラー、行 x に予期しない T_VARIABLE があります
では、このyield
キーワードとは何でしょうか? これは有効な PHP でしょうか? 有効な場合は、どのように使用すればよいのでしょうか?
ベストアンサー1
とはyield
?
キーワードyield
ジェネレータ関数からデータを返します:
ジェネレーター関数の核となるのは、yield キーワードです。最も単純な形式では、yield ステートメントは return ステートメントとよく似ていますが、関数の実行を停止して戻るのではなく、yield はジェネレーターをループするコードに値を提供し、ジェネレーター関数の実行を一時停止します。
ジェネレータ関数とは何ですか?
ジェネレータ関数は、よりコンパクトで効率的な書き方であり、イテレータ。これにより、計算して値を返す関数(xrange
)を定義できます。それをループする:
function xrange($min, $max) {
for ($i = $min; $i <= $max; $i++) {
yield $i;
}
}
[…]
foreach (xrange(1, 10) as $key => $value) {
echo "$key => $value", PHP_EOL;
}
これにより、次の出力が作成されます。
0 => 1
1 => 2
…
9 => 10
を使っ$key
て を制御することもできます。foreach
yield $someKey => $someValue;
ジェネレータ関数では、$someKey
は に表示したいものであり$key
、$someValue
は の値です$val
。質問の例では、 です$i
。
内部的には、非連想配列の場合と同様に、連続した整数キーが生成された値とペアになっていることに注意してください。キーを使用して生成値を設定することもできます。
通常の機能との違いは何ですか?
さて、なぜPHPのネイティブ関数を使わないのかと疑問に思うかもしれません。range
関数その出力を達成するために。その通りです。出力は同じです。違いはそこに到達する方法にあります。
PHPを使用するとrange
、それが実行され、メモリ内に数値の配列全体が作成され、return
その配列全体がループにforeach
渡されて、その配列が処理されて値が出力されます。言い換えると、はforeach
配列自体を操作します。range
関数と はforeach
1 回だけ「対話」します。郵便で荷物を受け取るようなものだと考えてください。配達員が荷物を渡して立ち去ります。そして、荷物全体を開封して、中身を取り出します。
ジェネレータ関数を使用すると、PHP は関数にステップインし、関数が end またはyield
キーワードに達するまでそれを実行します。 に達するとyield
、その時点の値が何であれ、それを外側のループに返します。その後、ジェネレータ関数に戻り、yield した場所から続行します。 はループxrange
を保持しているためfor
、 に達するまで実行され、yield します。とジェネレータがピンポンをしている$max
ようなものだと考えてください。foreach
なぜそれが必要なのですか?
明らかに、ジェネレーターはメモリ制限を回避するために使用できます。環境によっては、 を実行するとrange(1, 1000000)
スクリプトが致命的になりますが、ジェネレーターを使用すると問題なく動作します。または、Wikipedia では次のように説明されています。
ジェネレータは、要求に応じてのみ生成された値を計算するため、一度に計算するにはコストがかかったり不可能なシーケンスを表すのに役立ちます。これには、たとえば、無限シーケンスやライブ データ ストリームが含まれます。
ジェネレーターもかなり高速であるはずです。ただし、高速について話すときは、通常、非常に小さな数値について話していることに注意してください。したがって、今すぐにすべてのコードを変更してジェネレーターを使用する前に、ベンチマークを実行して、どこでそれが理にかなっているかを確認してください。
ジェネレーターのもう 1 つの使用例は、非同期コルーチンです。yield
キーワードは値を返すだけでなく、値を受け入れることもできます。詳細については、以下にリンクされている 2 つの優れたブログ投稿を参照してください。
いつから使えますかyield
?
ジェネレーターはPHP 5.5で導入されました。それより前のバージョンを使用するとyield
、キーワードに続くコードに応じてさまざまな解析エラーが発生します。そのため、そのコードから解析エラーが発生した場合は、PHP を更新してください。