Регистрация Войти
Войти через VK Войти через FB Войти через Google Войти через Яндекс
Войти через VK Войти через FB Войти через Google Войти через Яндекс
Поиск по сайту
Ссылки. Разъяснения »
« Синтаксис генераторов
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 ru ¶2 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 re ¶3 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