In Perl kann jede Funktion den Kontext definieren, in dem sie aufgerufen wird: skalar, listen oder void. Der Operator wantarray wird verwendet, um den Kontext zu bestimmen.
Beispiel:
sub foo { if (wantarray) { return (1, 2, 3); # Listen Kontext } else { return 42; # Skalar Kontext } } my @a = foo(); # (1, 2, 3) my $b = foo(); # 42 foo(); # Void Kontext
Besonderheit: Wenn wantarray nicht richtig verwendet wird, können unerwartete Werte zurückgegeben werden.
Was gibt die Funktion zurück, wenn sie abhängig vom Kontext ein Array und einen Skalar zurückgibt, und im Void-Kontext aufgerufen wird?
Antwort: Im Void-Kontext wird der Rückgabewert ignoriert, jedoch bleibt der Ausführungscode der Verzweigung durch wantarray. Daher sollten separate Behandlungen vorgesehen werden, wenn die Funktion Nebeneffekte hat. Zum Beispiel:
sub noisy { if (wantarray) { print "Wurde im Listen-Kontext aufgerufen"; return (1,2,3); } elsif (defined wantarray) { print "Wurde im Skalar-Kontext aufgerufen"; return 42; } else { print "Void!"; return; } }
Geschichte 1
In einem Projekt vergaß ein Ingenieur die Unterschiede im Kontext. Eine Funktion, die eine Liste von Dateinamen zurückgab, gab manchmal nur die Anzahl der Dateien (skalarer Kontext) statt der tatsächlichen Namen zurück – dies führte zu Datenverlust bei der Verkettung mit anderen Ergebnissen.
Geschichte 2
Bei der Entwicklung einer API zum Parsen von Headern gaben die Funktionen nur dann eine Liste zurück, wenn links explizit ein Array angegeben war (
my @headers = parse_headers()), und wenn sie alsif (parse_headers())aufgerufen wurden, wurde nur der erste Header zurückgegeben. Der Fehler wurde nicht sofort gefunden, da die Verarbeitung logisch erschien – aber das Verhalten unterschied sich in verschiedenen Teilen des Projekts.
Geschichte 3
Eine Funktion zur Suche nach Übereinstimmungen in einer Datei gab unterschiedlich viele Ergebnisse zurück, je nach Kontext. Infolgedessen traten beim Übergeben an map oder grep unerwartete Fehler auf: map erwartete eine Liste, erhielt jedoch undef – und im skalar Kontext wurde nur die Anzahl der gefundenen Übereinstimmungen gezählt. Das Problem wurde erst nach mehreren Releases entdeckt.