ProgrammationDéveloppeur Perl (backend/data)

Comment les itérateurs et les générateurs sont-ils implémentés et fonctionnent-ils en Perl ? Quels motifs de calcul paresseux courants sont appliqués et quelles sont leurs limitations ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

Il n'y a pas de générateurs natifs en Perl comme en Python, mais on peut réaliser des calculs paresseux et des itérateurs à l'aide de fermetures, de suivi d'état dans des variables lexicales et de fonctions-générateurs :

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

Pour des itérateurs complexes, on utilise souvent des modules CPAN (Iterator::Simple, List::Gen). Le motif paresseux classique consiste à retourner une sous-programme anonyme avec un état sauvegardé.

Inconvénients : pas de support intégré pour yield, de nombreux modules CPAN manquent de composabilité. La récursivité est également limitée par la taille de la pile.

Question piégée

Est-il possible de réaliser une liste paresseuse infinie de nombres de Fibonacci en Perl sans débordement de mémoire ?

Réponse : Oui, avec l'aide d'une fermeture :

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

Mais si les résultats sont stockés dans un tableau, il finira par saturer la mémoire (c'est-à-dire que seul le générateur lui-même est réellement « paresseux »).

Exemples d'erreurs réelles dues à l'ignorance des subtilités du sujet


Histoire

Un itérateur personnalisé a été écrit pour parcourir un énorme fichier, implémenté via un tableau à l'intérieur de l'objet. L'itérateur chargeait tout le fichier en mémoire - et à mesure que le fichier grossissait, le service commençait à provoquer des OOM lorsqu'il traitait plusieurs instances.


Histoire

Une fermeture-générateur pour une séquence de détails pour un rapport a conduit à une fuite de mémoire inattendue - la fermeture retenait par inadvertance une référence à un grand tableau de données d'entrée, empêchant le ramasse-miettes de fonctionner.


Histoire

Une tentative de réaliser un générateur complexe à l'aide de récursivité sans suivi de profondeur a conduit à un dépassement de la limite de la pile lors de la traitement de grandes données, au lieu de la « recherche paresseuse » attendue.