Чем отличается от сбора данных в результирующий массив с последующей его отдачей, кроме неочевидности происходящего, если не знать, что это за хрень, и, потенциально, усложнения отладки и багханта?
Тем, что данных может быть очень много из внешнего источника. Или может быть бесконечный ряд. Подготовка результатирующего массива тут бездумная трата ресурсов... их банально просто может не хватить.
соглашусь что код не столь очевиден, хотя ide у меня видит определение. Не юзаю, но в принципе ничего против не имею. Скажем так, если проект новый, почему бы и нет. В новых и трейты и иные веянения можно юзать. А вот в старых не вижу смысла внедрять: банально усложнит работу с кодом старым и лишние нейроны в голове лопнут).
Да, но в доках посмотри использование. Генератор не предоставляет поток. Он возвращает массив... То есть ты сначала пускаешь генератор, он наполняет переменную, потом ты юзаешь ее. Расход ресурсов такой же как и при использовании результирующего массива. Ну, разве что в момент возвращения значения нет фазы копирования, которая на несколько тактов процессора удваивает занимаемое количество ОП, после чего оно опять приходит в норму. Но, чтобы уронить что-то, пых должен за раз провернуть если не гигабайты, то сотни метров данных. Учитывая то, что это таки язык, заточенный именно под веб, сложно представить подобную ситуацию. Я с таким встречался только в тестовых кодах, либо "бенчмарках", когда сравниваешь пару-тройку алгоритмов на большой "дистанции". Но это же ресерч, а не повседневная нужда.
Нет, вы не поняли как он работает. Генератор - это форма итератора. В плюсах - более краткая и понятная запись. В минусах - движение только вперед. Первое обращение к функции генератора - выполняет функцию от начала до yield. Каждое последующее - от yield и до следующей встречи yield. Т.е. каждый вызов генератора не выполняет функцию с нуля, а продолжает с последней точки останова. Ну и возвращает то значение, которое написано в yield. Код (Text): function gen_one_to_three() { for ($i = 1; $i <= 3; $i++) { // Note that $i is preserved between yields. yield $i; } } $generator = gen_one_to_three(); В $generator сейчас будет не [1, 2, 3], а ссылка на генератор, который можно использовать как итератор. По сути любой генератор можно переделать как итератор (класс Iterator). Просто генератор - более компактная запись. Добавлено спустя 1 минуту 29 секунд: http://php.net/manual/ru/language.generators.comparison.html Вот тут пример есть. Генератор и аналогичный ему итератор.
PHP уже давно вышел и стадии "заточенный под веб" и вполне используется и для других задач. Да и кто, как не вы фанат экономии каждого байта. Другое дело, что реальных кейсов действительно не так много. Но они есть. Кроме того, генераторы - удобный способ написания кода демона взаимодействующего с асинхронными сервисами.
Пара практичных примеров. Ведение лога: Код (PHP): function log_writer($fname) { $file = new SplFileObject($fname, 'a'); while (true) { $line = yield; $file->fwrite($line . PHP_EOL); } } $log = log_writer('log.txt'); $log->send('Start'); $log->send('Finish'); оператор yield обеспечивает обратную связь. Возврат строки mysql из своего класса без необходимости предварительной агрегации в массив. Экономит память: Код (PHP): public function selectRows($sql) { $result = $this->query($sql); while ($row = $result->fetch_assoc()) { yield $row; } } foreach ($db->selectRows($sql) as $row) { } плюс перед отдачей массива в том, что строки не фетчатся, пока не потребуются. Плюс перед отдачей объекта mysqli_result в большей гибкости итератора, по сравнению с результом. А если нужен именно массив сразу со всеми строками, можно сделать так: Код (PHP): $array = iterator_to_array($db->selectRows($sql));
В php7 также вводится конструкция yield from. То есть можно проделывать такую штуку: Код (PHP): function gen2($i) { yield $i; yield $i*2; } function gen1() { yield from [1,2]; yield from gen2(4); } foreach (gen1() as $i) { var_dump($i); }