Генераторы

Последнее обновление: 11.03.2021

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

Для возвращения значения из функции применяется оператор 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;
}

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

<?php
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
}

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

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850