Немаловажное про генераторы в PHP

Наткнулся на важный пост о генераторах в ПХП, я их попробовал использовать, ещё когда они были в альфе. Хорошая штука, мне после Пайтона их в языке не хватало.

Суть же рассматриваемой проблемы в следующем. Смотрите, вот функция, которая возвращает построчно файл и пример её вызова:
function getLines($file) {
    $f = fopen($file, 'r');
    while ($line = fgets($f)) {
        yield $line;
    }
    fclose($f);
}

foreach (getLines("file.txt") as $line) {
     echo $line;
}
Пока всё чудесно, ничего странного и необычного, а теперь представьте, что нам нужно прочитать только четыре первые строки:
foreach (getLines("file.txt") as $n => $line) {
    if ($n > 5) break;
    echo $line;
}
Если в файле их было больше, то в функции getLines вызов fclose не выполнится никогда — до него программа просто не дойдёт, файл останется открытым, память занятой и так далее. Плохо. Что делать?

Оказывается, документация обходит этот вопрос стороной, а вот автор введения в ПХП этой конструкции позаботился о том, чтобы эту тему раскрыть — если прочитать соответствующий RFC, становится ясно как быть.

Оказывается, при высвобождении ссылки на генератор, внутри его обязаны выполнится все блоки finally, т.е. вышеприведённый код нужно переписать следующим образом:
function getLines($file) {
    $f = fopen($file, 'r');
    try {
        while ($line = fgets($f)) {
            yield $line;
        }
    } finally {
        fclose($f);
    }
}
14 августа 2013 20:18

Аноним (инкогнито)
14 августа 2013, 22:20

Евгений, часто вижу, что вы пишите слитно "нехватало". Неужели это правильно?

Евгений Степанищев (bolknote.ru)
14 августа 2013, 23:16, ответ предназначен Аноним

Нет, разумеется, но я пока не могу побороть в себе эту привычку. Если не успеваю вычитать текст, то моё «нехватало» проскальзывает. Спасибо!

aktuba (инкогнито)
15 августа 2013, 00:25

Когда программил на Delphi, выработалась привычка: все, что открыто - закрыть в finally. Пройдет время - будет такая привычка и у php-ов)

hshhhhh (hshhhhh.name)
15 августа 2013, 00:57

Слушай, я не понимаю зачем эти генераторы нужны. Ну вот честно не понимаю. Как по мне сахар сахаром.
Если бы пхп был асинхронным -- богом дарованная штука, а в синхронном пхп ну зачем они?

Почему их именно "не хватало" если это не более чем сахар.

Евгений Степанищев (bolknote.ru)
15 августа 2013, 06:15, ответ предназначен hshhhhh (hshhhhh.name):

Мне, сове, тяжело в 7 утра придумывать хорошие примеры :) Лучше прочитать статьи про генераторы в Пайтоне, были где-то хорошие. Это другой стиль мышления.

Пока писал это, вспомнил, что у Вани была статья, касающаяся генераторов, которая поможет понять одну из областей где они полезны: http://softwaremaniacs.org/blog/2010/09/18/ijson/

http://grishaev.me/ (инкогнито)
15 августа 2013, 10:11, ответ предназначен hshhhhh (hshhhhh.name):

Главное их преимущество - элементы генератора не хранятся в памяти все разом, как в списке/массиве. Хранится только текущий элемент и состояние генератора для вычисления нового элемента.

hshhhhh (hshhhhh.name)
15 августа 2013, 11:53, ответ предназначен Евгений Степанищев (bolknote.ru):

Пока писал это, вспомнил, что у Вани была статья, касающаяся генераторов, которая поможет понять одну из областей где они полезны: http://softwaremaniacs.org/blog/2010/09/18/ijson/
Я, как сова, не очень вник, но потом дочитаю. На первый взгляд я понял что оно возращает key:value из жсона и это круто потому что не жрётся память, но если value будет охеренным объектом -- уже бесполезно.

А делать рекурсивные вхождения -- непонятно как потом обрабатывать.

Я, вроде, понимаю зачем нужны генераторы, но рассматриваю их исключительно как сахар. Хотя надо попробовать поиграться чтоли.

hshhhhh (hshhhhh.name)
15 августа 2013, 11:54, ответ предназначен http://grishaev.me/

Главное их преимущество - элементы генератора не хранятся в памяти все разом, как в списке/массиве. Хранится только текущий элемент и состояние генератора для вычисления нового элемента.
ну с ФС проблемы не существует.
с БД не прокатит.
ЖСОН и прочие сериализованные данные, на мой взгляд, универсально парсить не получится.

не понимаю :).

hshhhhh (hshhhhh.name)
15 августа 2013, 12:00, ответ предназначен Евгений Степанищев (bolknote.ru):

Я, как сова, не очень вник, но потом дочитаю. На первый взгляд я понял что оно возращает key:value из жсона и это круто потому что не жрётся память, но если value будет охеренным объектом -- уже бесполезно.
Ну тут я оказался неправ, но автор пишет что у него получится приррост по скорости 30%. При этом обрабатывать это неудобно. То есть да, для оптимизации можно пользовать, но лучше хранить код красивым если есть возможность :).

Евгений Степанищев (bolknote.ru)
15 августа 2013, 15:55, ответ предназначен hshhhhh (hshhhhh.name):

Код будет красивым :)

Паша (инкогнито)
15 августа 2013, 20:18

Давид недавно об этом тоже написал
http://david-m.livejournal.com/1294116.html

Евгений Степанищев (bolknote.ru)
16 августа 2013, 18:56, ответ предназначен Паша

Так по моей ссылке он об этом и пишет.

http://4idroid.com (инкогнито)
16 августа 2013, 23:07, ответ предназначен Евгений Степанищев (bolknote.ru):

А разве у вас не включено автоматическое исправление ошибок?

4idroid.com (инкогнито)
16 августа 2013, 23:11

А вообще случайно наткнулся на ваш блог и меня сразу заинтересовал этот пост. Полезная информация, спасибо

Евгений Степанищев (bolknote.ru)
17 августа 2013, 09:18, ответ предназначен 4idroid.com

А разве у вас не включено автоматическое исправление ошибок?
Не включено автоматическое исправление ошибок где?

Ваше имя или адрес блога (можно OpenID):

Текст вашего комментария, не HTML:

Кому бы вы хотели ответить (или кликните на его аватару)