Blog de programación, errores, soluciones

PHP / generators – Que son los generadores en php

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.
Cargar un array en memoria puede ocasionar que se exceda el límite de memoria, o requiera una cantidad considerable de tiempo de procesado para generarse.

Los generators o las funciones generadoras nos permiten apalear este problema ya que no retorna todo en un solo return, en cambio las funciones generadoras no usan return sino que usan la sentencia yield.

Las funciones generadoras pueden devolver tantos yield como sea posible.

Básicamente un generador es una función contiene la sentencia yield, en vez de return, la función generadora cuando se la llama por primera vez al tener esta sentencia crea un objeto de clase generator.

Objeto Generador

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.

Su estructura es esta:

Generator implements Iterator {
/* Métodos */
public current ( void ) : mixed
public getReturn ( void ) : mixed
public key ( void ) : mixed
public next ( void ) : void
public rewind ( void ) : void
public send ( mixed $value ) : mixed
public throw ( Throwable $exception ) : mixed
public valid ( void ) : bool
public __wakeup ( void ) : void
}

Cuando se llama a una función generadora, devuelve un objeto que puede ser iterado. Cuando se itera sobre ese objeto (por ejemplo, con un bucle foreach), PHP llamará a la función generadora cada vez que necesite un valor, y guardará el estado del generador cuando este provea un valor con yield para que ese estado pueda ser recuperado cuando el próximo valor sea requerido.

Ejemplo que se da en php.net

<?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(1, 9, 2) as $number) {
    echo "$number ";
}
echo "\n";

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

En este ejemplo que se da en php.net se compara la funcion range con una función generadora xrange(). Tal cual como se comento ante xrange usara menos memoria. Según cálculos que hicieron xrange(0,10000,1) usaria 1kb mientras que range(0,10000,1) en esa cantidad de números usaria 100mb.

Recuerde las funciones generadoras las creas tu, y es tu habilidad de detectar cuando usarla o cuando no lo que hara que tenga sentido su uso.

Mas de php en: PHP 101 -mini tutorial de PHP

Referencias

Ayudame: Por favor deja un comentario antes de irte, tu opinión es bienvenida. Si te gusta el contenido comparte.