MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Generatoare

Un generator oferă o funcție care generează un set de valori.

Pentru a returna o valoare dintr-o funcție se folosește operatorul yield. Spre deosebire de return, operatorul yield păstrează starea funcției, permițându-i să continue execuția de unde s-a oprit.

Exemplu de funcție generator simplă:

function generator() {
   yield 21;
}

Aici, funcția generator returnează de fapt un singur număr, 21. Totuși, putem itera rezultatul funcției generator într-o buclă, la fel ca un array obișnuit:

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

În mod similar, generatorul poate returna mai multe valori:

function generateNumbers() {
   for ($i = 0; $i <= 5; $i++) {
       yield $i;
   }
}

foreach(generateNumbers() as $number) {
   echo $number; // 012345
}

În acest caz, funcția generator generateNumbers() folosește o buclă pentru a genera valori de la 0 la 5 inclusiv. Este echivalent cu:

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

Când iterăm în buclă, parcurgem de fapt rezultatul funcției ca pe un array obișnuit, fiecare element având un index numeric începând de la zero:

<?php
function generateNumbers() {
   for ($i = 10; $i <= 15; $i++) {
       yield $i;
   }
}

foreach(generateNumbers() as $index => $number) {
   echo "$index - $number<br/>";
}
?>

Rezultatul funcției:

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

Cu ajutorul operatorului from, putem defini un array ca sursă de date pentru generator:

function generateNumbers() {
   yield 1;
   yield from [2, 3, 4];
   yield 5;
}

foreach(generateNumbers() as $number) {
   echo $number; // 12345
}

În acest caz, funcția generateNumbers() pentru generarea unei părți din date utilizează array-ul [2, 3, 4] prin expresia yield from [2, 3, 4].

Funcția generator poate accepta parametri, permițând astfel personalizarea comportamentului generatorului:

function generateNumbers($start, $end) {
   for($i = $start; $i < $end; $i++) {
       yield $i;
   }
}

foreach(generateNumbers(4, 9) as $number) {
   echo $number; // 45678
}

Poate apărea întrebarea: de ce avem nevoie de generatoare? Nu putem să iterăm pur și simplu un array obișnuit? De exemplu:

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

Problema este că, atunci când lucrăm cu un array, întregul array este încărcat în memorie. În cazul unor volume mici de date, acest aspect poate fi ignorat. Însă, pe măsură ce dimensiunea array-ului crește, cresc și costurile și pierderile în performanță.

Generatoarele sunt menite să rezolve această problemă, extrăgând doar o valoare la un moment dat când se apelează funcția, economisind astfel resursele de calcul.

← Lecția anterioară Lecția următoare →