Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> PHP

Generators vs Iterator Objects ใน PHP

บทนำ

เมื่อเรียก Generator Function ภายในจะคืน Object ของ Class Generator ซึ่ง Implement Iterator Interface Interface Iterator กำหนด Abstract Methods 5 ตัว:

  • Iterator::current - คืนค่า Element ปัจจุบัน
  • Iterator::key - คืนค่า Key ของ Element ปัจจุบัน
  • Iterator::next - เลื่อนไป Element ถัดไป
  • Iterator::rewind - ม้วนกลับไป Element แรก
  • Iterator::valid - ตรวจสอบตำแหน่งปัจจุบันถูกต้องไหม

Generator ทำงานเหมือน Forward-only Iterator มี Methods สำหรับจัดการ State รวมถึงส่งค่าเข้าและรับค่าจาก Generator

Generator as Iterator

ตัวอย่าง Generator Function Yield บรรทัดในไฟล์ สามารถ Traverse ด้วย Foreach เรียก Iterator Methods เช่น current() และ next() ได้ แต่ rewind() จะโยน Exception เพราะ Generator เป็น Forward-only:

<?php
function fileGenerator($name) {
    $fileHandle = fopen($name, 'r');
    while ($line = fgets($fileHandle)) {
        yield $line;
    }
    fclose($fileHandle);
}

$name = "test.txt";
$file = fileGenerator($name);
foreach ($file as $line) {
    echo $line;
}
$file->rewind();  // Error!
echo $file->current();
$file->next();
echo $file->current();
?>

ผลลัพธ์

PHP Fatal error: Uncaught Exception: Cannot rewind a generator that was already run

ความแตกต่างสำคัญ: Generator vs Iterator Implementation

คุณสมบัติGeneratorIterator Implementation
Boilerplate Codeน้อยมาก (แค่ yield)มาก (Implement 5 Methods)
State ManagementAuto (PHP จัดการ)Manual (Developer จัดการ)
Rewindableไม่ได้ (Forward-only)ได้ (ถ้า Implement rewind)
MemoryLow (Lazy)ขึ้นอยู่กับ Implementation
Send Valuesได้ (send())ไม่ได้โดยตรง
Return Valueได้ (getReturn())ไม่ได้

Generator Methods เพิ่มเติม

  • send($value) - ส่งค่าเข้า Generator (รับผ่าน yield expression)
  • throw($exception) - โยน Exception เข้า Generator
  • getReturn() - รับค่า Return ของ Generator
  • valid(), current(), key(), next(), rewind() - Iterator Methods

ตัวอย่าง send()

<?php
function logger() {
    while (true) {
        $msg = yield;
        echo "LOG: $msg\n";
    }
}

$log = logger();
$log->send("First message");
$log->send("Second message");
$log->send("Third message");
?>

ผลลัพธ์

LOG: First message
LOG: Second message
LOG: Third message

สรุป

  • Generator = Syntax Sugar สำหรับ Iterator แบบ Forward-only
  • เหมาะกับ One-pass Iteration (ไฟล์, Stream, Large Dataset)
  • ต้องการ Rewind/Multiple Passes → Implement Iterator Interface เอง
  • Generator ให้ Advanced Features: send, throw, getReturn