In Perl, qualsiasi funzione può determinare in quale contesto viene chiamata: scalare, elencato o void. L'operatore wantarray viene utilizzato per determinare il contesto.
Esempio:
sub foo { if (wantarray) { return (1, 2, 3); # Contesto elencato } else { return 42; # Contesto scalare } } my @a = foo(); # (1, 2, 3) my $b = foo(); # 42 foo(); # Contesto void
Particolarità: se non si utilizza wantarray correttamente, si possono restituire valori inaspettati.
Cosa restituirà la funzione, se a seconda del contesto restituisce un array e un scalare, mentre viene chiamata in contesto void?
Risposta: In contesto void, il valore restituito viene ignorato, ma il codice di esecuzione nella ramificazione tramite wantarray rimane. Pertanto, è necessario prevedere un'elaborazione separata se la funzione esegue azioni collaterali. Ad esempio:
sub noisy { if (wantarray) { print "Chiamato in contesto elencato"; return (1,2,3); } elsif (defined wantarray) { print "Chiamato in contesto scalare"; return 42; } else { print "Void!"; return; } }
Storia 1
In un progetto, un ingegnere dimenticava le differenze di contesto. La funzione, che restituiva una lista di nomi di file, a volte "restituiva" solo il numero di file (contesto scalare) invece dei loro nomi — questo portava a una perdita di dati durante la concatenazione con altri risultati.
Storia 2
Durante lo sviluppo di un'API per il parsing degli header, le funzioni restituivano una lista solo se era presente esplicitamente un array a sinistra (
my @headers = parse_headers()), e se chiamate comeif (parse_headers()), veniva restituito solo il primo header. Il bug è stato trovato non subito, poiché l'elaborazione sembrava logica — ma il comportamento era diverso in diverse parti del progetto.
Storia 3
Una funzione per cercare corrispondenze in un file restituiva un numero variabile di risultati a seconda del contesto. Di conseguenza, passando ad essa in map o grep si verificavano errori inaspettati: map si aspettava una lista, ma riceveva undef — e in contesto scalare veniva conteggiato solo il numero di corrispondenze trovate. Il problema è stato scoperto solo dopo alcuni rilasci.