PHPジェネレータークラス入門:yieldで実現する省メモリな反復処理
はじめに
foreach などのループ構文で大規模なデータコレクションを走査すると、大量のメモリを消費し、処理にも相当な時間がかかります。ジェネレータ(Generator) を使えば、こうしたオーバーヘッドなしにデータセットを反復処理できます。
ジェネレータ関数は通常の関数とよく似ていますが、return 文の代わりに yield キーワードを使用します。yield は繰り返し実行されることで、反復処理に渡す値を順番に生成します。
yield キーワードはジェネレータ機構の中核となる存在です。使い方は return に似ていますが、関数の実行を終了させるわけではありません。次の反復値を返したうえで、関数の実行をその場で一時停止します。再び値が要求されると、中断した箇所から処理が再開される仕組みです。
クラスの構文
Generator implements Iterator {
/* メソッド */
public current ( void ) : mixed
public getReturn ( void ) : mixed
public key ( void ) : mixed
public next ( void ) : void
public rewind ( void ) : void
public send ( mixed $value ) : mixed
public throw ( Throwable $exception ) : mixed
public valid ( void ) : bool
public __wakeup ( void ) : void
}主なメソッド
public Generator::current ( void ) : mixed — 現在 yield された値を取得します。
public Generator::getReturn ( void ) : mixed — ジェネレータの戻り値を取得します。
public Generator::key ( void ) : mixed — 現在 yield された値のキーを取得します。
public Generator::next ( void ) : void — ジェネレータの実行を再開します。NULL を引数として Generator::send() を呼び出すのと同じ効果があります。
public Generator::rewind ( void ) : void — イテレータを巻き戻します。すでに反復処理が開始されている場合は例外がスローされます。
public Generator::send ( mixed $value ) : mixed — 指定した値を現在の yield 式の結果としてジェネレータへ送信し、実行を再開します。
public Generator::throw ( Throwable $exception ) : mixed — ジェネレータ内へ例外をスローし、実行を再開します。
public Generator::valid ( void ) : bool — イテレータがまだ有効(閉じられていない)かどうかを判定します。
public Generator::__wakeup ( void ) : void — ジェネレータはシリアライズできないため、例外をスローします。
Generator クラスは Iterator インターフェースを実装しています。Generator オブジェクトは new による直接インスタンス化はできません。ユーザー定義関数内に yield キーワードが含まれている場合、その関数を呼び出すと自動的に Generator オブジェクトが生成されます。
ジェネレータの使用例
ジェネレータは Iterator インターフェースを実装しているため、foreach ループで yield された値を簡単に走査できます。
例1:foreach での反復処理
<?php
function squaregenerator(){
for ($i=1; $i<=5; $i++){
yield $i*$i;
}
}
$gen=squaregenerator();
foreach ($gen as $val){
echo $val . " ";
}
?>出力結果
上記プログラムを実行すると、次の出力が得られます。
1 4 9 16 25
次の例では、ジェネレータクラスの current() メソッドと next() メソッドを使って yield された値を走査します。ループの継続条件は valid() メソッドで判定しています。
例2:イテレータメソッドを使った反復処理
<?php
function squaregenerator(){
for ($i=1; $i<=5; $i++){
yield $i*$i;
}
}
$gen=squaregenerator();
while ( $gen->valid() ){
echo "key: " . $gen->key(). " value: ". $gen->current() . "
";
$gen->next();
}
?>出力結果
上記プログラムを実行すると、次の出力が得られます。
key: 0 value: 1 key: 1 value: 4 key: 2 value: 9 key: 3 value: 16 key: 4 value: 25
まとめ
PHP のジェネレータは、yield キーワードによって値を逐次生成しながら反復処理を行える強力な仕組みです。大きな配列を事前にメモリ上に展開する必要がないため、メモリ使用量を大幅に抑えられます。Iterator インターフェースを実装しているため、foreach とも自然に連携でき、可読性の高いコードを書くことが可能です。
-
PHPのget_class_methods()関数とは?使い方をわかりやすく解説
get_class_methods()関数の概要PHPのget_class_methods()関数は、指定したクラスに定義されているメソッド名の一覧を取得するための関数です。引数に渡されたクラス(name_of_class)に定義されたすべてのメソッド名を配列として返し、エラーが発生した場合はNULLを返します。構文get_class_methods(class)パラメータname_of_class − メソッド名を取得したいクラス名を文字列またはオブジェクトで指定します。必須パラメータです。戻り値get_class_methods()関数は、name_of_c
-
PHPのclass_exists()関数とは?使い方とサンプルコードをわかりやすく解説
概要PHPのclass_exists()関数は、指定したクラスがすでに定義されているかどうかをチェックするための関数です。クラスが定義済みであればTRUEを、未定義であればFALSEを返します。プラグインの読み込みや条件分岐によるクラスの動的な利用など、柔軟なプログラミングに役立ちます。構文class_exists(class, autoload)パラメータclass − 存在を確認したいクラスの名前。autoload − デフォルトでオートロード機構(__autoload / spl_autoload_call)を呼び出すかどうか。省略した場合のデフォルト値はTRUE