Información general de los generadores

(PHP 5 >= 5.5.0, PHP 7)

Los generadores proporcionan un modo fácil de implementar iteradores simples sin la sobrecarga o complejidad de implementar una clase que implemente la interfaz Iterator.

Un generador permite escribir código que utilice foreach para iterar sobre un conjunto de datos sin que sea necesario cargar el array en memoria, lo que puede ocasionar que se exceda el límite de memoria, o requiera una cantidad considerable de tiempo de procesado para generarse. En su lugar, se puede escribir una función generadora, que es igual que una función normal, con la salvedad de que en vez de hacer un solo return, un generador puede invocar yield tantas veces como necesite para proporcionar valores por los que iterar.

Un ejemplo simple de esto es reimplementar la función range() como un generador. La función estándar range() tiene que generar un array con cada uno de los valores y devolverlo, lo que puede resultar en arrays grandes: por ejemplo, llamar range(0, 1000000) resultará en más de 100 MB de memoria utilizada.

Como alternativa, se puede implementar un generador xrange(), que sólo necesitará memoria para crear un objeto Iterator y controlar el estado actual del generador de manera interna, lo que no ocupa más de 1 kilobyte.

Ejemplo #1 Implementando range() como generador

<?php
function xrange($start$limit$step 1) {
    if (
$start $limit) {
        if (
$step <= 0) {
            throw new 
LogicException('Step tiene que ser +ve');
        }

        for (
$i $start$i <= $limit$i += $step) {
            
yield $i;
        }
    } else {
        if (
$step >= 0) {
            throw new 
LogicException('Step tiene que ser -ve');
        }

        for (
$i $start$i >= $limit$i += $step) {
            
yield $i;
        }
    }
}

/*
 * Obsereve que tanto range() como xrange() producen la misma
 * salida a continuación.
 */

echo 'Números impares de una cifra de range():  ';
foreach (
range(192) as $number) {
    echo 
"$number ";
}
echo 
"\n";

echo 
'Números impares de una cifra de xrange():  ';
foreach (
xrange(192) as $number) {
    echo 
"$number ";
}
?>

El resultado del ejemplo sería:

Números impares de una cifra de range():  1 3 5 7 9 
Números impares de una cifra de xrange(): 1 3 5 7 9 

Objetos Generator

Cuando una función generadora es invocada por primera vez, se devuelve un objeto de la clase interna Generator. Este objeto implementa la interfaz Iterator de la misma forma que lo haría un objeto iterador de solo avance, y proporciona métodos que pueden ser invocados para manipular el estado del generador, incluyendo el envío de valores hacia y la devolución de valores desde él.