In Perl, le sottoprogrammazioni accettano argomenti tramite una variabile-array speciale @_, dove vengono automaticamente inseriti tutti i parametri passati. Una caratteristica di Perl è che i parametri vengono passati a @_ per riferimento, il che significa che modificare gli elementi all'interno della funzione cambia i loro valori all'esterno.
Per evitare modifiche inaspettate ai dati passati, è consigliato copiare i parametri in variabili:
sub sum { my ($a, $b) = @_; return $a + $b; }
Le funzioni Perl restituiscono sempre un elenco di valori, e il risultato della funzione è l'ultimo elenco calcolato o un esplicito operatore return.
sub minmax { my ($x, $y) = @_; return ($x < $y ? $x : $y, $x > $y ? $x : $y); } my ($min, $max) = minmax(4, 7); # $min = 4; $max = 7
Se chiami una funzione in un contesto scalare, essa restituirà il numero di elementi restituiti, se non imballi il risultato in un scalare.
Come passare un gran numero di variabili a una funzione Perl senza modificare accidentalmente i valori delle variabili originali?
Rispondono inconsapevolmente: "Devi semplicemente copiare gli argomenti in variabili proprio come al solito!"
Risposta corretta:
La copia funziona solo per scalari. Se stai lavorando con array o hash, usa riferimenti per gestire il passaggio dei dati in modo esplicito ed evitare copie per riferimento:
sub modify { my ($arr_ref) = @_; push @$arr_ref, 'new'; # modifica l'array originale } my @data = (1, 2, 3); modify(\@data); # ora @data = (1, 2, 3, 'new')
Storia
Storia 1
In un grande script per l'elaborazione di report, una funzione interna modificava i valori degli elementi di un array passato dalla programmazione principale. Di conseguenza, dopo l'esecuzione della funzione, i dati originali erano distorti. L'errore consisteva nel fatto che l'autore della funzione non faceva copie dei valori in ingresso, pensando che le modifiche fossero locali, ma questo non è vero per @_ con gli array.
Storia 2
Durante la migrazione di script da Perl 4 (dove le variabili venivano copiate in modo diverso), il team si è imbattuto in un problema: il passaggio di hash nidificati portava a una "perdita" inaspettata di dati tra le chiamate alle sottoprogrammazioni - la modifica dei campi di un hash in una funzione influenzava altre parti del codice. La ragione era il riferimento a un hash nell'elenco @_.
Storia 3
Un sviluppatore ha implementato una funzione che restituiva un array di risultati, ma nel punto di chiamata usava un contesto scalare:
$count = func(@params);. Ci si aspettava che alla variabile fosse assegnato il valore del primo elemento restituito, ma in realtà in$countc'era il numero di elementi nell'elenco, il che ha portato a ritardi nei calcoli e confusione.