ProgrammazioneSviluppatore Perl (backend/data)

Как realizada e funzionano i iterator e generator in Perl? Quali pattern comuni di calcolo pigro vengono applicati e quali sono i loro limiti?

Supera i colloqui con l'assistente IA Hintsage

Risposta

In Perl non ci sono generator nativi come in Python, ma è possibile implementare calcoli pigri e iterator con chiusure, tracciamento dello stato in variabili lessicali e funzioni generatori:

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

Per iterator più complessi si usano spesso moduli CPAN (Iterator::Simple, List::Gen). Un classico pattern pigro è il ritorno di una sottoprogramma anonima con stato salvato.

Svantaggi: non c'è supporto integrato per yield, molti moduli CPAN mancano di composizione. La ricorsione è anche limitata dalle dimensioni dello stack.

Domanda trabocchetto

È possibile implementare una lista pigra infinita di numeri di Fibonacci in Perl senza esaurire la memoria?

Risposta: Sì, usando una chiusura:

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

Ma se si memorizzano i risultati in un array, esso alla lunga esaurirà la memoria (cioè il vero "pigro" è solo il generatore stesso).

Esempi di errori reali a causa della mancata conoscenza delle sottigliezze dell'argomento


Storia

In un progetto è stato scritto un proprio iteratore per scorrere un file enorme, implementato tramite un array all'interno di un oggetto. L'iteratore caricava l'intero file in memoria — e con l'aumento del file il servizio cominciava a chiamare OOM quando si lavorava con più istanze.


Storia

Una chiusura-generatore per una sequenza di dettagli per il report ha portato a una inesperata perdita di memoria — all'interno della chiusura veniva accidentalmente tenuta un riferimento a un grande array di dati di input, il che impediva al garbage collector di funzionare.


Storia

Il tentativo di implementare un generatore complesso usando la ricorsione senza tracciare la profondità ha portato a superare il limite dello stack quando si elaboravano dati realmente grandi, invece del previsto "scorrimento" pigro.