こんにちは。よっしーです(^^)
今日は、PHPのGeneratorsについてご紹介します。
背景
PHP8.2を利用したAPIを開発しているときにGeneratorsを利用したので、そのときの調査内容を備忘としてのこしました。
こちらのサイトを参考にしています。
yield fromによるジェネレータの委譲
ジェネレータの委譲を使用すると、別のジェネレータ、Traversableオブジェクト、または配列から値をyieldできます。yield from
キーワードを使用します。外側のジェネレータは、内側のジェネレータ、オブジェクト、または配列からすべての値をyieldします。これが無効になるまで、その後外側のジェネレータで実行が続行されます。
ジェネレータがyield from
と組み合わされる場合、yield from
式は内部ジェネレータによって返される値も返します。
注意
yield from
を使って配列に格納する場合(例えば、iterator_to_array()
を使用する場合)、キーはリセットされません。yield from
は、Traversableオブジェクトや配列が返すキーを保持します。そのため、一部の値は別のyield
またはyield from
と共通のキーを共有する可能性があります。これらの値を配列に挿入すると、同じキーの以前の値が上書きされることになります。
この問題が影響する一般的なケースは、iterator_to_array()
がデフォルトでキー付きの配列を返す場合です。これは予期しない結果を引き起こす可能性があります。iterator_to_array()
には第二のパラメータpreserve_keys
があり、これをfalse
に設定することで、Generatorが返すキーを無視してすべての値を収集できます。
サンプル1
<?php
function inner() {
yield 1; // key 0
yield 2; // key 1
yield 3; // key 2
}
function gen() {
yield 0; // key 0
yield from inner(); // keys 0-2
yield 4; // key 1
}
// pass false as second parameter to get an array [0, 1, 2, 3, 4]
var_dump(iterator_to_array(gen()));
このコードは、PHPでジェネレータを使用する例です。ジェネレータは、特定の条件で値を生成するための強力な機能です。
- ジェネレータ関数の定義:
gen
というジェネレータ関数が定義されています。- この関数は、
yield 0;
でキー0の値を返します。 yield from inner();
で内部のジェネレータ関数inner()
からキー0から2までの値を受け取ります。yield 4;
でキー1の値を返します。
- ジェネレータの利用:
iterator_to_array(gen())
を使って、ジェネレータから値を配列に変換します。- 第二のパラメータとして
false
を渡すことで、キーをリセットせずにすべての値を収集します。
- 出力結果:
- 上記のコードを実行すると、以下のような出力が得られます:
array(3) {
[0]=>
int(1)
[1]=>
int(4)
[2]=>
int(3)
}
サンプル2
<?php
function count_to_ten() {
yield 1;
yield 2;
yield from [3, 4];
yield from new ArrayIterator([5, 6]);
yield from seven_eight();
yield 9;
yield 10;
}
function seven_eight() {
yield 7;
yield from eight();
}
function eight() {
yield 8;
}
foreach (count_to_ten() as $num) {
echo "$num ";
}
このコードは、PHPでジェネレータを使用する例です。ジェネレータは、特定の条件で値を生成するための強力な機能です。
- ジェネレータ関数の定義:
count_to_ten
というジェネレータ関数が定義されています。- この関数は、以下の値を順番に生成します:
- 1
- 2
- 配列
[3, 4]
の要素 ArrayIterator([5, 6])
の要素seven_eight()
関数からの値- 9
- 10
- ジェネレータの利用:
foreach (count_to_ten() as $num)
を使って、ジェネレータから値を取り出します。- 各値は
$num
に代入され、スペースで区切って表示されます。
- 出力結果:
- 上記のコードを実行すると、以下のような出力が得られます:
1 2 3 4 5 6 7 8 9 10
サンプル3
<?php
function count_to_ten() {
yield 1;
yield 2;
yield from [3, 4];
yield from new ArrayIterator([5, 6]);
yield from seven_eight();
return yield from nine_ten();
}
function seven_eight() {
yield 7;
yield from eight();
}
function eight() {
yield 8;
}
function nine_ten() {
yield 9;
return 10;
}
$gen = count_to_ten();
foreach ($gen as $num) {
echo "$num ";
}
echo $gen->getReturn();
このコードは、PHPでジェネレータを使用する例です。ジェネレータは、特定の条件で値を生成するための強力な機能です。
- ジェネレータ関数の定義:
count_to_ten
というジェネレータ関数が定義されています。- この関数は、以下の値を順番に生成します:
- 1
- 2
- 配列
[3, 4]
の要素 ArrayIterator([5, 6])
の要素seven_eight()
関数からの値- 9
- 10
- ジェネレータの利用:
foreach ($gen as $num)
を使って、ジェネレータから値を取り出します。- 各値は
$num
に代入され、スペースで区切って表示されます。
- 出力結果:
- 上記のコードを実行すると、以下のような出力が得られます:
1 2 3 4 5 6 7 8 9 10
おわりに
今日は、PHPのGeneratorsについてご紹介しました。
何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント