HaxeからPHPのGeneratorを掌握する:遅延評価を型安全に包み込む極致
HaxeのPHPターゲットを利用する際、最も強力かつ見落とされがちなのが、PHPの`Generator`(`yield`)とHaxeの`Iterable`の統合だ。PHPのGeneratorはメモリ効率に優れた遅延評価の宝庫だが、Haxeの静的型システムから見れば「ただの`Dynamic`な何か」に映る。
これを適切に抽象化せずに呼び出すのは、型安全性を放棄するに等しい。今回は、PHPのジェネレータをHaxeのイテレータとして完全に適合させ、コンパイル時に型整合性を担保する設計パターンを伝授する。
なぜ「そのまま」呼び出してはいけないのか
PHPのジェネレータは`\Generator`クラスのインスタンスを返すが、Haxe側でこれを安易に扱おうとすると、`iterator()`や`next()`のインターフェースが欠落し、実行時に`Fatal error`を招く。
我々が目指すべきは、「PHP側の遅延評価の恩恵を享受しつつ、Haxe側では静的型付けされたイテレータとして扱う」という設計だ。
実装パターン:`PhpGeneratorAdapter`の構築
PHPの`Generator`をラップし、Haxeの`Iterator
package php.lib;
import php.Generator;
/
- PHPのGeneratorをHaxeのIterableとして適合させるアダプター
/
@:forward
abstract PhpIterable
public inline function new(gen:Generator) {
// PHPのGeneratorはTraversableを実装しているため、
// HaxeのIteratorインターフェースに適合させるためのラッパー
this = cast gen;
}
@:from
public static inline function fromGenerator
return new PhpIterable(cast gen);
}
}
実践:Composerパッケージの遅延評価APIを叩く
例えば、外部のComposerパッケージが巨大なログファイルを`yield`で返しているとしよう。これをHaxe側で安全に消費するコードはこうなる。
import php.Lib;
import php.lib.PhpIterable;
class LogProcessor {
public static function main() {
// 外部PHPライブラリが返すGeneratorを想定
var logGenerator = ExternalLogger.fetchLogs();
// HaxeのIteratorとして扱う
var logs:PhpIterable
for (line in logs) {
// ここでは完全に型安全にStringとして扱える
trace(‘Processing: $line’);
}
}
}
// 外部PHPライブラリの型定義 (extern)
extern class ExternalLogger {
public static function fetchLogs():php.Generator;
}
この設計の極意:なぜこれが「美しい」のか
1. メモリオーバーヘッドのゼロ化
`@:forward`と`inline`を活用することで、コンパイル時にアダプターのオーバーヘッドを完全に排除している。生成されるPHPコードは、直接`Generator`を操作するものとほぼ同等になる。
2. 型の強制力
PHP側がどんなに混沌とした配列を返してこようとも、`PhpIterable
3. 非同期ストリーミングとの親和性
将来的に`yield`を用いたストリーミング処理をPHPの非同期イベントループと組み合わせる際、このラッパーがあれば、Haxe側のコードを一切書き換えることなく、PHP側の実装を`yield`から`Async Generator`へシームレスに移行できる。
注意点:パフォーマンスと罠
- 反復回数の制限: PHPの`Generator`は一度しか走査できない(Rewind不可)。`for`ループを二度回そうとすると例外が発生する。Haxe側で再利用が必要な場合は、`Lambda.array()`等で一度メモリ上に展開する判断が必要だ。
- 例外処理: PHPの`Generator`内で発生した`Exception`は、Haxe側に適切に伝播する。`try-catch`ブロックをループの外側に配置し、遅延評価の失敗を適切にハンドリングせよ。
結びに:Haxeを「PHPの型安全なレイヤー」として使う
Haxeを単なるトランスパイラとして使うのは、フェラーリで近所のコンビニに行くようなものだ。
PHPの動的な柔軟性を、Haxeの静的な剛性で包み込む。この「ハイブリッドな設計」こそが、大規模なプロダクション環境でバグを寄せ付けない真のアーキテクチャである。
次にコードを書くときは、単に動くコードではなく、「コンパイラがあなたの意図を代弁してくれるコード」を追求してほしい。健闘を祈る。