ジェネレータの構文ジェネレータ関数の見た目はふつうの関数とほぼ同じです。違うのは、値を返すのではなく、 必要なだけ値を yield することです。 yield が含まれていれば、どんな関数でもジェネレータ関数です。 ジェネレータ関数が呼ばれると、反復処理が可能なオブジェクトを返します。 このオブジェクトを (foreach ループなどで) 反復させると、 値が必要になるたびに PHP がオブジェクトの反復メソッドを呼びます。 そして、ジェネレータが値を yield した時点の状態を保存しておき、 次に値が必要になったときにはそこから再開できるようにします。 yield できる値がなくなると、ジェネレータは単純に呼び出し元に制御を戻します。 呼び出し元のコードでは、配列の要素をすべて処理し終えた後のように、そのまま処理が続きます。
yield キーワードジェネレータ関数の肝となるのが yield キーワードです。 最もシンプルな書きかたをすると、yield 文の見た目は return 文とほぼ同じになります。 ただ、return の場合はそこで関数の実行を終了して値を返すのに対して、 yield の場合はジェネレータを呼び出しているループに値を戻して ジェネレータ関数の実行を一時停止します。 例1 値を yield する単純な例
上の例の出力は以下となります。 1 2 3
値とキーの yieldPHP は、数値添字の配列だけでなく連想配列にも対応しています。ジェネレータも例外ではありません。 先ほどの例のように単なる値を yield するだけでなく、 値と同時にキーも yield することができます。 キーと値のペアを yield する構文は連想配列の定義とよく似ており、次のようになります。 例2 キー/値 のペアの yield
上の例の出力は以下となります。 1: PHP $が大好き 2: Python インデントが大好き 3: Ruby ブロックが大好き null 値の yield
何も引数を渡さずに yield を呼ぶと、 例3
上の例の出力は以下となります。 array(3) { [0]=> NULL [1]=> NULL [2]=> NULL } 参照による yieldジェネレータ関数は、値を参照として yield することもできます。 関数の結果を参照で返す ときと同じように、関数名の前にアンパサンドを付けます。 例4 参照による値の yield
上の例の出力は以下となります。 2... 1... 0... yield from によるジェネレータの委譲ジェネレーターを委譲することで、 別のジェネレータや Traversable オブジェクトあるいは配列から、 yield from キーワードを使って値を yield できます。 外側のジェネレータは、内側のジェネレータ (あるいはオブジェクトや配列) から受け取れるすべての値を yield し、 何も取得できなくなったら外側のジェネレータの処理を続行します。 ジェネレータに対して yield from を使った場合は、 yield from 式は内側のジェネレータが返す任意の値を返します。 警告
iterator_to_array を用いた、配列への格納yield from は配列のキーをリセットしません。 Traversable オブジェクトや array が返すキーを、そのまま利用します。つまり、別々の yield や yield from から取得した異なる値のキーが、重複することもありえます。 これを配列に格納すると、後からきた値がそれまでの値を上書きします。
iterator_to_array を使う場合に問題になることがよくあります。
この関数はデフォルトで数値添字配列を返すので、予期せぬ結果を引き起こす可能性があります。
iterator_to_array には二番目のパラメータ
例5 yield from と iterator_to_array
上の例の出力は以下となります。 array(3) { [0]=> int(1) [1]=> int(4) [2]=> int(3) } 例6 yield from の基本的な使いかた
上の例の出力は以下となります。 1 2 3 4 5 6 7 8 9 10 例7 yield from の返す値
上の例の出力は以下となります。 1 2 3 4 5 6 7 8 9 10 |