こんにちは。よっしーです(^^)
今日は、PHPのGeneratorsについてご紹介します。
背景
PHP8.2を利用したAPIを開発しているときにGeneratorsを利用したので、そのときの調査内容を備忘としてのこしました。
こちらのサイトを参考にしています。
ジェネレータの構文
ジェネレータ関数は通常の関数と似ていますが、値を返す代わりに、ジェネレータは必要なだけの値を「yield」します。yield
を含む任意の関数はジェネレータ関数となります。
ジェネレータ関数が呼び出されると、イテレーション可能なオブジェクトが返されます。そのオブジェクトを反復処理すると(例えば、foreach
ループを使用して)、PHPはオブジェクトのイテレーションメソッドを必要なたびに呼び出し、ジェネレータが値を返すときにその状態を保存します。次に値が必要なときに再開できるようにします。
もはや返す値がない場合、ジェネレータは単純に終了し、呼び出し元のコードは配列の値がなくなったかのように続行します。
注意:
ジェネレータは値を返すことができ、Generator::getReturn()
を使用して取得できます。
yieldキーワード
ジェネレータ関数の中心にはyield
キーワードがあります。最も単純な形では、yield
文はreturn
文と似ていますが、関数の実行を停止して戻る代わりに、yield
はジェネレータをループしているコードに値を提供し、ジェネレータ関数の実行を一時停止します123。
ジェネレータ関数は、必要なだけの値を生成するためにyield
を使用します。yield
を含む関数はジェネレータ関数となります。ジェネレータ関数が呼び出されると、イテレータ可能なオブジェクトが返され、そのオブジェクトを反復処理するときに必要な値を提供します。ジェネレータは値を生成するたびにその状態を一時的に保存し、次の値が必要なときに再開できるようにします。
yield
を使ったジェネレータは、大量のデータを効率的に処理する際や、リアルタイムでデータを生成する必要がある場合に特に有用です。
例1 yieldの簡単な例
<?php
function gen_one_to_three() {
for ($i = 1; $i <= 3; $i++) {
// Note that $i is preserved between yields.
yield $i;
}
}
$generator = gen_one_to_three();
foreach ($generator as $value) {
echo "$value\n";
}
このコードは、PHPでジェネレータを使用する例です。ジェネレータは、特定の条件で値を生成するための強力な機能です。
- ジェネレータ関数の定義:
gen_one_to_three
というジェネレータ関数が定義されています。- この関数は、
for
ループを使用して、1から3までの整数を生成します。 yield $i;
の部分で、$i
の値をジェネレータに返します。
- ジェネレータの利用:
gen_one_to_three()
を呼び出すと、ジェネレータオブジェクトが返されます。foreach
ループを使って、ジェネレータから値を取り出します。- 各値は
$value
に代入され、echo "$value\n";
で表示されます。
- 出力結果:
- 上記のコードを実行すると、以下のような出力が得られます:
1
2
3
注意:
内部的には、連続した整数キーは、非連想配列と同様に、生成された値とペアになります。
キーを指定して値を生成する
PHPは連想配列もサポートしており、ジェネレータも同様です。上記の例で示したように、単純な値を生成するだけでなく、同時にキーを生成することもできます。
キーと値のペアを生成するための構文は、連想配列を定義する際に使用されるものと非常に似ています。以下にその例を示します。
サンプル1
<?php
function gen_key_value_pair() {
yield 'apple' => 'red';
yield 'banana' => 'yellow';
yield 'grape' => 'purple';
}
$generator = gen_key_value_pair();
foreach ($generator as $fruit => $color) {
echo "$fruit is $color.\n";
}
このコードを実行すると、以下の出力が得られます:
apple is red.
banana is yellow.
grape is purple.
サンプル2
<?php
/*
* The input is semi-colon separated fields, with the first
* field being an ID to use as a key.
*/
$input = <<<'EOF'
1;PHP;Likes dollar signs
2;Python;Likes whitespace
3;Ruby;Likes blocks
EOF;
function input_parser($input) {
foreach (explode("\n", $input) as $line) {
$fields = explode(';', $line);
$id = array_shift($fields);
yield $id => $fields;
}
}
foreach (input_parser($input) as $id => $fields) {
echo "$id:\n";
echo " $fields[0]\n";
echo " $fields[1]\n";
}
このコードは、PHPでジェネレータを使用する例です。ジェネレータは、特定の条件で値を生成するための強力な機能です。
- ジェネレータ関数の定義:
input_parser
というジェネレータ関数が定義されています。- この関数は、セミコロンで区切られたフィールドからなる入力文字列を受け取ります。
explode("\n", $input)
で入力文字列を行ごとに分割し、各行のフィールドを取得します。array_shift($fields)
でフィールドの先頭の要素を取り出し、それをIDとして使用します。yield $id => $fields;
の部分で、IDとフィールドのペアをジェネレータに返します。
- ジェネレータの利用:
input_parser($input)
を呼び出すと、ジェネレータオブジェクトが返されます。foreach
ループを使って、ジェネレータからIDとフィールドを取り出します。- 各IDとフィールドは
$id
と$fields
に代入され、それぞれ表示されます。
- 出力結果:
- 上記のコードを実行すると、以下のような出力が得られます:
1:
PHP
Likes dollar signs
2:
Python
Likes whitespace
3:
Ruby
Likes blocks
おわりに
今日は、PHPのGeneratorsについてご紹介しました。
何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント