제네레이터와 Iterator 객체 비교

제네레이터와 Iterator 객체 비교

제네레이터의 장점

제네레이터의 가장 큰 장점은 단순함이에요. Iterator 클래스를 직접 구현하는 것에 비해 작성해야 할 상용구(boilerplate) 코드가 훨씬 적고, 코드도 전반적으로 훨씬 읽기 쉬워요. 예를 들어 아래 함수와 클래스는 서로 동일한 동작을 해요.

<?php
function getLinesFromFile($fileName) {
    if (!$fileHandle = fopen($fileName, 'r')) {
        return;
    }

    while (false !== $line = fgets($fileHandle)) {
        yield $line;
    }

    fclose($fileHandle);
}

// versus...

class LineIterator implements Iterator {
    protected $fileHandle;

    protected $line;
    protected $i;

    public function __construct($fileName) {
        if (!$this->fileHandle = fopen($fileName, 'r')) {
            throw new RuntimeException('Couldn\'t open file "' . $fileName . '"');
        }
    }

    public function rewind() {
        fseek($this->fileHandle, 0);
        $this->line = fgets($this->fileHandle);
        $this->i = 0;
    }

    public function valid() {
        return false !== $this->line;
    }

    public function current() {
        return $this->line;
    }

    public function key() {
        return $this->i;
    }

    public function next() {
        if (false !== $this->line) {
            $this->line = fgets($this->fileHandle);
            $this->i++;
        }
    }

    public function __destruct() {
        fclose($this->fileHandle);
    }
}

유연성에 따른 비용

이런 유연성에는 그래도 비용이 따르는데요, 제네레이터는 앞으로만 진행하는(forward-only) 이터레이터라서 반복이 시작된 뒤에는 처음으로 되감을 수 없어요. 이 말은 곧 같은 제네레이터를 여러 번 반복할 수도 없다는 뜻이에요. 다시 순회하려면 제네레이터 함수를 다시 호출해서 제네레이터를 새로 만들어야 해요.

참고

  • 객체 반복 — 객체를 반복하는 방법에 대한 문서

원문: PHP Manual, "Comparing generators with Iterator objects"