บทนำ
การวนลูปข้อมูลจำนวนมากด้วย foreach ต้องการหน่วยความจำมากและเวลาประมวลผลนาน ด้วย generators สามารถวนลูปข้อมูลได้โดยไม่มี overhead เหล่านี้ Generator function คล้ายกับฟังก์ชันปกติ แต่แทน return statement จะใช้คำสำคัญ yield เพื่อ execute ซ้ำๆ จนกว่าจะหมดค่าที่จะวนลูป
คำสำคัญ yield เป็นหัวใจของ generator mechanism แม้จะดูคล้าย 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 - รับค่าส่งคืนของ generator
public Generator::key ( void ) - mixed - รับคีย์ของค่าที่ yield
public Generator::next ( void ) - void - Resume การทำงานของ generator เหมือนกับการเรียก Generator::send() ด้วย NULL argument
public Generator::rewind ( void ) - void - Rewind iterator หากการวนลูปเริ่มแล้ว จะ throw exception
public Generator::send ( mixed $value ) : mixed - ส่งค่าที่กำหนดให้ generator เป็นผลลัพธ์ของ yield expression ปัจจุบัน และ resume generator
public Generator::throw ( Throwable $exception ) - mixed - โยน exception เข้า generator และ resume การทำงาน
public Generator::valid ( void ) - bool - ตรวจสอบว่า iterator ถูกปิดแล้วหรือยัง
public Generator::__wakeup ( void ) - void - Throw exception เพราะ generators ไม่สามารถ serialize ได้
Generator class implements Iterator interface ไม่สามารถสร้าง instance ผ่าน new ได้ ฟังก์ชัน user-defined ที่มี yield keyword จะสร้าง object ของ generator class
Generator Example
เนื่องจาก generator implements Iterator interface สามารถใช้ foreach loop วนลูปค่าที่ yield ได้
<?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() ของ generator class วนลูปค่าที่ yield เงื่อนไขลูปตรวจสอบด้วย valid()
ตัวอย่าง
<?php function squaregenerator(){ for ($i=1; $i<=5; $i++){ yield $i*$i; } } $gen = squaregenerator(); while ( $gen->valid() ){ echo "key: " . $gen->key(). " value: ". $gen->current() . "\n"; $gen->next(); } ?>ผลลัพธ์
โปรแกรมข้างต้นแสดงผลลัพธ์ดังนี้
key: 0 value: 1 key: 1 value: 4 key: 2 value: 9 key: 3 value: 16 key: 4 value: 25