Разликата между :
function patapan(): int { for ($i = 1; $i <= 3; $i++) { return $i; } }
и
function patapan() { for ($i = 1; $i <= 3; $i++) { yield $i; } }
е, че първият случай „patapan()“ ако го използваш така:
echo patapan();
echo patapan();
echo patapan();
echo patapan();
…
ще върне
1 1 1 1 …
защото всеки път ще започва for-а отначало.
При вторият, patapan() ще върне обект от интерфейс Generator, който трябва да се изцикли и при всяка итерация ще return-ва поредната стойност.
Демек, ще пази до къде е стигнал for-а за да може да не започва всеки път от начало. Но как програмно става това „пазене“ на това, до къде сме стигнали?
Отоворът се крие в Iterator Design Pattern.
function patapan(): Generator
{
for ($i = 1; $i <= 3; $i++) {
yield $i;
}
}
$ptpns = patapan();
foreach ($ptpns as $ptpn) {
echo $ptpn;
}
// 1 2 3
Функция, която имплементира Generator интерфейса, е напълно обикновена функция, с тази разлика, че вместо да върне резултат подобно на всяка функция, тя връща обект, който може да се изцикли, например с най-обикновен foreach, и при всяка итерация ще получаваме текущата стойност, като също ще се запазва до къде сме стигнали.
Удобно е, в смисъл, че най-малкото страшно пести памет, когато трябва да се използват например резултати от DB SELECT заявки, защото дава възможност да се използва резултатът един вид „на части“, „per iteration basis„,
демек, не ми давай наведнъж всичко, а ми давай резултата едно по едно като разбира всеки път си пази до къде си стигнал, за да знаеш кое ще е следващото.
Или с други думи, „по-ефектифен начин да връщаш стойност докато още изцикляш всички стойности“ – (that will calculate and return values while you are looping over it)
Когато използваме обикновена фукнкция, натрупваме резултата и тогава го връщаме с return.
Koгато използваме yield – започваме да изпълняваме и стигнем ли то yield – връщаме каквото е в момента на дадената итерация, запазваме до къде сме стигнали и следващата итерация не се повтаряме.