PHP: Сравнение генераторов с объектами класса Iterator - Manual

    Ссылки. Разъяснения »
    « Синтаксис генераторов

    Edit Report a Bug

    Сравнение генераторов с объектами класса Iterator

    Главное преимущество генераторов - это их простота. Гораздо меньше шаблонного кода надо написать, по сравнению с реализацией объекта класса Iterator, и этот код гораздо более простой и понятный. К примеру, эти функция и класс делают одно и то же.ё

    function getLinesFromFile($fileName) {
        if (!$fileHandle = fopen($fileName, 'r')) {
            return;
        }
     
        while (false !== $line = fgets($fileHandle)) {
            yield $line;
        }
     
        fclose($fileHandle);
    }
    // Против...
    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);
        }
    }

    Но за эту простоту, впрочем, приходится платить: генераторы могут быть только однонаправленными итераторами. Их нельзя перемотать назад после старта итерации. Это также означает, что один и тот-же генератор нельзя использовать несколько раз - генератор необходимо пересоздавать каждый раз, как вы захотите его использовать.


    function getLinesFromFile($fileName) {
        if (!$fileHandle = fopen($fileName, 'r')) {
            throw new RuntimeException('Couldn\'t open file "' . $fileName . '"');
        }
        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() { }
        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);
        }
    }


    10
    sergeyzsg at yandex dot ru2 years ago
    function getLinesFromFile($fileHandle) {
        while (false !== $line = fgets($fileHandle)) {
            yield $line;
        }
    }
    if ($fileHandle = fopen($fileName, 'r')) {
        /*
        something with getLinesFromFile
        */
        fclose($fileHandle);
    }


    1
    sou at oand dot re3 years ago
    I think to be more similar the samples in the function, throw a new exception is better. But looking into "Generator syntax" session, you can see there this: "An empty return statement is valid syntax within a generator and it will terminate the generator.". By this point of view, we can imagine that this is just to exemplify an usage of the empty return.




    Смотрите также:
    Описание на ru2.php.net
    Описание на php.ru