ProgramaciónDesarrollador Perl (backend/data)

¿Cómo se implementan y funcionan los iteradores y generadores en Perl? ¿Qué patrones comunes de cálculo perezoso se aplican y cuáles son sus limitaciones?

Supere entrevistas con el asistente de IA Hintsage

Respuesta

En Perl no hay generadores nativos como en Python, pero se pueden implementar cálculos perezosos e iteradores mediante cierres, seguimiento del estado en variables léxicas y funciones generadoras:

sub counter { my $x = shift; return sub { return $x++; }; } my $it = counter(5); print $it->(), ", ", $it->(); # 5, 6

Para iteradores complejos, a menudo se utilizan módulos de CPAN (Iterator::Simple, List::Gen). Un patrón clásico de pereza es devolver una subprograma anónima con estado guardado.

Desventajas: no hay soporte incorporado para yield, muchos módulos de CPAN carecen de compostibilidad. La recursión también está limitada por el tamaño de la pila.

Pregunta trampa

¿Se puede implementar una lista infinita perezosa de números de Fibonacci en Perl sin desbordar la memoria?

Respuesta: Sí, mediante cierre:

sub fibonacci { my ($a, $b) = (0, 1); return sub { ($a, $b) = ($b, $a+$b); return $a; }; } my $fib = fibonacci(); print $fib->(), ", ", $fib->(), ", ", $fib->();

Pero si se almacenan los resultados en un arreglo, eventualmente desbordará la memoria (es decir, realmente el único "perezoso" es el generador mismo).

Ejemplos de errores reales por falta de conocimiento de los matices del tema


Historia

En un proyecto se escribió un iterador propio para recorrer un archivo enorme, implementado mediante un arreglo dentro de un objeto. El iterador cargó todo el archivo en memoria, y al crecer el archivo el servicio comenzó a generar OOM al trabajar con múltiples instancias.


Historia

Un cierre-generador para una secuencia de detalles para un informe provocó una fuga de memoria inesperada: dentro del cierre se mantenía accidentalmente una referencia a un gran arreglo de datos de entrada, lo que impedía que el recolector de basura funcionara.


Historia

Intentar implementar un generador complejo mediante recursión sin rastrear la profundidad llevó a superar el límite de la pila al procesar datos realmente grandes, en lugar de la esperada iteración "perezosa".