Bon, en premier lieu, il n'y a pas de piège. Les lignes d'entrées contiennent deux informations, une étiquette et une valeur. Le programme identifie les groupes de lignes consécutives ayant la même étiquette, et produit pour chaque groupe une ligne contenant cette étiquette commune d'une part, et la somme des valeurs des lignes constituant le groupe d'autre part.
Pour ceux qui s'interrogeraient sur l'absence de boucle dans le programme, c'est dû aux flags -n, -l et -a utilisés lors de l'invocation de perl en plus de -e (sous la forme compacte -nlae)
- -ne '...' provoque l'insertion d'une boucle autour du code ... et est equivalent à -e 'LINE: while (<>) { ... }'
- -l ajoute l'instruction chomp dans la boucle ce qui donne -e 'LINE: while (<>) { chomp; ... }'
- -a ajoute l'instruction @F = split dans la boucle ce qui donne -e 'LINE: while (<>) { chomp; @F = split; ... }'
On comprend donc que le code
$F[0] ne $g->[0] and $g = bless [@F] or $g->[1] += $F[1] sera exécuté pour chaque ligne du fichier d'entrée, $F[0] contenant l'étiquette et $F[1] la valeur lues pour cette ligne.
Ceci posé, le code est un peu bizarre... C'est une expression logique, de la forme
A and B or C, dont on n'utilise pas le résultat... En fait, à cause des règles de précédence des opérateurs logiques, du fait que B est toujours vrai, et de l'évaluation minimale effectuée par Perl pour les expressions logiques, celle expression est ici équivalente au test
if (A) { B } else { C }, soit
1 2 3 4 5
| if ($F[0] ne $g->[0])) {
$g = bless [@F]
} else {
$g->[1] += $F[1]
} |
ce qui est peut-être un peu plus facile à appréhender. Les formes
$g->[0] et
$g->[1] indiquent clairement que $g est une référence à un tableau de 2 entrées, et on voit bien le fonctionnement de l'algorithme : $g va représenter le groupe en cours de traitement, avec l'étiquette dans
$g->[0] et la somme dans
$g->[1]. Le test
if ($F[0] ne $g->[0]) permet de détecter qu'on change de groupe. Si la condition est vraie (les étiquettes du groupe et de la ligne courante diffèrent), et donc qu'on doit créer un nouveau groupe, on exécute le corps du if,
$g = bless [@F] qui initialise le nouveau groupe $g par une référence à un tableau contenant une copie des champs de la ligne courante. Si la condition est fausse, on incrémente la somme du groupe de la valeur trouvée dans la ligne courante.
Incidemment $g n'étant pas initialisée (sauf peut être dans Mytery.pm mais cela semble improbable), est indéfinie lors du traitement de la première ligne. Le déréférencement
$g->[0] produit dans ce cas
undef qui en contexte de comparaison textuelle se transforme en chaîne vide. La condition du if est alors vraie, et on crée un nouveau groupe dès la première ligne.
C'est limpide.
Partager