En Perl, toute fonction peut déterminer dans quel contexte elle est appelée : scalaire, en liste ou vide. L'opérateur wantarray est utilisé pour déterminer le contexte.
Exemple :
sub foo { if (wantarray) { return (1, 2, 3); # Contexte en liste } else { return 42; # Contexte scalaire } } my @a = foo(); # (1, 2, 3) my $b = foo(); # 42 foo(); # Contexte vide
Particularité : si wantarray n'est pas utilisé correctement, il est possible de retourner des valeurs inattendues.
Que renverra la fonction si, en fonction du contexte, elle renvoie un tableau et un scalaire, et est appelée dans un contexte vide ?
Réponse : En contexte vide, la valeur retournée est ignorée, mais le code d'exécution de la branche selon wantarray reste. Par conséquent, il faut prévoir un traitement séparé si la fonction effectue des effets secondaires. Par exemple :
sub noisy { if (wantarray) { print "Appel dans le contexte de liste"; return (1,2,3); } elsif (defined wantarray) { print "Appel dans le contexte scalaire"; return 42; } else { print "Vide !"; return; } }
Histoire 1
Dans un projet, un ingénieur oubliait les différences de contexte. La fonction qui retournait une liste de noms de fichiers renvoyait parfois seulement le nombre de fichiers (contexte scalaire) au lieu des noms eux-mêmes — cela entraînait une perte de données lors de la concaténation avec d'autres résultats.
Histoire 2
Lors du développement d'une API pour l'analyse des en-têtes, les fonctions retournaient une liste uniquement si un tableau était explicitement présent à gauche (
my @headers = parse_headers()), et si elle était appelée commeif (parse_headers()), seul le premier en-tête était renvoyé. Le bug n'a pas été découvert immédiatement, car le traitement semblait logique — mais le comportement différait dans différentes parties du projet.
Histoire 3
Une fonction de recherche de correspondances dans un fichier renvoyait un nombre différent de résultats selon le contexte. En conséquence, lors du passage à map ou grep, des erreurs inattendues se produisaient : map s'attendait à une liste, mais recevait undef — alors qu'en contexte scalaire, seul le nombre de correspondances trouvées était compté. Le problème n'a été découvert qu'après plusieurs versions.