Какой будет возвращаемый тип у метода с конструкцией yield в PHP?

Ответ

Метод, использующий yield, возвращает объект встроенного класса Generator.

Generator — это внутренний класс, реализующий интерфейсы Iterator и Traversable. Это означает, что возвращаемый объект можно использовать в цикле foreach.

Пример с явным указанием типа (PHP 7.0+):

function generateSequence(int $start, int $end): Generator {
    for ($i = $start; $i <= $end; $i++) {
        yield $i;
    }
}

$gen = generateSequence(1, 5);
var_dump($gen instanceof Generator); // bool(true)
echo get_class($gen); // Generator

foreach ($gen as $value) {
    echo $value . ' '; // 1 2 3 4 5
}

Ключевые особенности:

  • Ленивые вычисления: Значения генерируются по требованию, а не все сразу, что экономит память.
  • Итератор: Объект Generator управляет своим состоянием (текущее значение, ключ, возможность продолжения).
  • Двусторонняя коммуникация: Через Generator::send($value) можно передавать значения в генератор, а yield может возвращать их.

Важно: Нельзя использовать return для возврата значения из такой функции в PHP < 7.0. В PHP 7.0+ return может использоваться для завершения генератора и установки его конечного возвращаемого значения, доступного через $gen->getReturn().

Ответ 18+ 🔞

Слушай, а вот насчёт этих генераторов в пыхе — это вообще отдельная песня, ёпта. Представь себе: есть у тебя функция, которая вместо того чтобы нагло вывалить на тебя весь массив данных и сожрать всю оперативку, как последняя свинья, просто лениво плюётся значениями по одному, когда ты её об этом просишь. И возвращает она не просто что-то, а объект встроенного класса Generator.

Этот Generator — он такой хитрожопый внутренний класс, который прикидывается и Iterator, и Traversable одновременно. Короче, его можно тупо в foreach воткнуть, и он отработает как надо.

Вот смотри, как это выглядит, если ты любитель явно указывать типы (PHP 7.0+):

function generateSequence(int $start, int $end): Generator {
    for ($i = $start; $i <= $end; $i++) {
        yield $i;
    }
}

$gen = generateSequence(1, 5);
var_dump($gen instanceof Generator); // bool(true)
echo get_class($gen); // Generator

foreach ($gen as $value) {
    echo $value . ' '; // 1 2 3 4 5
}

А теперь главные фишки, из-за которых это всё вообще стоит использовать:

  • Ленивые вычисления, ядрёна вошь! Значения не генерируются все сразу, а только тогда, когда ты их реально запросил. Памяти жрёт — ноль ебать, особенно если данных овердохуища.
  • Он сам себе итератор. Этот объект Generator сам помнит, на каком он значении, какой ключ и можно ли двигаться дальше. Умная штука, бля.
  • Двустороннее движение, ёбана! Ты можешь не только получать от него значения, но и пихать их обратно через Generator::send($value). А yield в этот момент может их принимать и возвращать. Настоящий диалог получается, а не просто монолог.

Важный момент, чувак: В пыхе до седьмой версии использовать return в такой функции для возврата значения — это была идея хуй с горы. Ничего не работало. А вот начиная с PHP 7.0, return можно юзать, чтобы красиво завершить генератор и задать финальное возвращаемое значение. Достать его потом можно через $gen->getReturn(). Вот такая вот эволюция, бля.