こんにちは。よっしーです(^^)
今日は、PHPのGeneratorsについてご紹介します。
背景
PHP8.2を利用したAPIを開発しているときにGeneratorsを利用したので、そのときの調査内容を備忘としてのこしました。
こちらのサイトを参考にしています。
ジェネレータの概要
ジェネレータは、Iteratorインターフェースを実装するクラスのオーバーヘッドや複雑さなしに、簡単にシンプルなイテレータを実装する方法を提供します。
ジェネレータを使用すると、メモリ内で配列を構築する必要なく、foreachを使用してデータセットを反復処理できます。これにより、メモリ制限を超過する可能性があるか、生成にかなりの処理時間が必要な場合に対処できます。代わりに、ジェネレータ関数を記述できます。これは通常の関数と同じですが、一度だけではなく、必要な回数だけyieldできます。
これの単純な例として、range()関数をジェネレータとして再実装することが挙げられます。標準のrange()関数は、すべての値を含む配列を生成して返す必要があり、これにより大きな配列が生成される可能性があります。たとえば、range(0, 1000000)を呼び出すと、100 MB以上のメモリが使用されます。
代替として、xrange()ジェネレータを実装できます。これはIteratorオブジェクトを作成し、ジェネレータの現在の状態を内部で追跡するために必要なメモリだけを常に使用します。これにより、1キロバイト未満になります。
例1 ジェネレータとしての range() の実装
<?php
function xrange($start, $limit, $step = 1) {
if ($start <= $limit) {
if ($step <= 0) {
throw new LogicException('Step must be positive');
}
for ($i = $start; $i <= $limit; $i += $step) {
yield $i;
}
} else {
if ($step >= 0) {
throw new LogicException('Step must be negative');
}
for ($i = $start; $i >= $limit; $i += $step) {
yield $i;
}
}
}
/*
* Note that both range() and xrange() result in the same
* output below.
*/
echo 'Single digit odd numbers from range(): ';
foreach (range(1, 9, 2) as $number) {
echo "$number ";
}
echo "\n";
echo 'Single digit odd numbers from xrange(): ';
foreach (xrange(1, 9, 2) as $number) {
echo "$number ";
}
上記の例では下記の出力が期待されます:
Single digit odd numbers from range(): 1 3 5 7 9
Single digit odd numbers from xrange(): 1 3 5 7 9
Generatorオブジェクト
ジェネレータ関数が呼び出されると、内部のジェネレータクラスの新しいオブジェクトが返されます。このオブジェクトは、前方のみに進むイテレータオブジェクトと同様に、Iteratorインターフェースを実装しており、ジェネレータの状態を操作するために呼び出すことができるメソッドを提供します。これには値を送信したり、値を返したりするものも含まれます。
おわりに
今日は、PHPのGeneratorsについてご紹介しました。
何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント