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 que 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 hacía y la devolución de valores desde él.
Su estructura es esta:
Description / DescripciónGenerator 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 función range
con una función generadora xrange()
. Tal cual como se comentó 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.
Referencias
- Anterior: generadores en PHP
- Siguiente: excepciones predefinidas en PHP