Полный цикл в digital

Генераторы и оператор yield

Генератор предоставляет функцию, которая генерирует набор значений.

Для возвращения значения из функции применяется оператор yield. Но в отличие от return оператор yield сохраняет состояние функции, позволяя ей продолжать работу с того места, когда остановилось ее выполнение.

Например, определим простейшую функицию генератора:

<?
function generator() {
yield 21;
}

Здесь функция генератора фактически возвращает только одно число 21. Тем не менее мы можем перебирать результат функции генератора в цикле как стандартный массив:

<?
foreach(generator() as $number) {
echo $number; // 21
}

Подобным образом генератор может возвращать и большее количество значений:

<?
function generateNumbers() {
for ($i = 0; $i <= 5; $i++) { 
yield $i; 
}
} 
foreach(generateNumbers() as $number) {  
echo $number; // 012345 
}

В данном случае функиция генератора generateNumbers() с помощью цикла генерирует значения от 0 до 5 включительно. Это все равно, если бы написали:

function generateNumbers() {
yield 0;
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
}

При переборе в цикле мы фактически перебираем результат функции как обычный массив, каждый элемент которого имеет числовой индекс, начиная с нуля:

<?
function generateNumbers()
{
for ($i = 10; $i <= 15; $i++) {
yield $i;
}
}
foreach(generateNumbers() as $index => $number) {
echo "$index - $number<br/>"; // 012345
}

Результат функции:

0 - 10
1 - 11
2 - 12
3 - 13
4 - 14
5 - 15

С помощью оператора from можно определять массив - источник данных для генератора:

<?
function generateNumbers() {
yield 1;
yield from [2, 3, 4];
yield 5;
}
foreach(generateNumbers() as $number) {
echo $number; // 12345
}

В данном случае функция generateNumbers() для генерации часть данных берет из массива [2, 3, 4] с помощью выражения yield from [2, 3, 4].

Функция генератора, как и любая функция может принимать параметры, что позволяет настраивать поведение генератора:

<?
function generateNumbers($start, $end) {
for($i = $start; $i < $end; $i++) { 
yield $i; 
} 
} 
foreach(generateNumbers(4, 9) as $number) {
echo $number; // 45678 
}

Но естественно может возникнуть вопрос: а зачем нужны генераторы? Разве мы не можем с тем же успехом перебират обычный массив? Например:

<?
$numbers = [1, 2, 3, 4, 5];
foreach($numbers as $number) {
echo $number; // 12345
}

Дело в том, что при работе с массивом весь массив загружается в память. При небольших объемах проблема может быть игнорироваться. Но чем больше размер массива, соответственно тем больше издержки и потери в производительности. Именно эту проблему и призваны решить генераторы, которые извлекают только одно значение одномоментно при обращении к функции, экономя тем самым вычислительные ресурсы.

Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!
Эйч Маркетинг