ProgrammazioneFull Stack Perl Developer

Quali sono i metodi esistenti per passare argomenti alle sottoprogrammi in Perl e come organizzare il passaggio per riferimento? Quali sono le sottigliezze del lavoro con @_ e quando è necessario il passaggio per riferimento?

Supera i colloqui con l'assistente IA Hintsage

Risposta

In Perl, tutti gli argomenti delle funzioni vengono gestiti attraverso l'array @_. Quando una sottoprogramma viene chiamata, tutti i parametri passati si trovano all'interno di questo array, e inizialmente è una lista, non una copia, cioè se si modifica $_[0], si modifica l'originale.

Passaggio per valore:

sub foo { my ($arg1, $arg2) = @_; $arg1 = 10; # Solo la variabile locale cambia }

Passaggio per riferimento:

sub bar { my ($array_ref) = @_; push @$array_ref, 42; } my @data = (1,2,3); bar(\@data); # @data ora è (1,2,3,42)

Sottigliezze:

  • Se vuoi modificare l'array o l'hash originale, passa un riferimento.
  • Le variabili normali ($foo, $bar) all'interno di @_ sono alias degli argomenti originali, ma durante lo sviluppo con my ($a, $b) = @_ vengono create copie.
  • Per array e hash durante un passaggio normale, il loro contenuto viene espanso in una lista, e perderai i confini: devi passare un riferimento o usare la specifica dei shift.

Domanda trabocchetto

Se si passa un array a una funzione in Perl così: myfunc(@arr), e all'interno della funzione si accede a $_[0], cosa ci sarà lì?

Risposta corretta: Ci sarà il primo elemento del valore dell'array, e non un riferimento all'intero array! Per passare un array come oggetto intero, utilizza un riferimento: myfunc(\@arr).

Esempio:

sub print_first { print $_[0], " "; } my @a = qw/foo bar baz/; print_first(@a); # Mostrerà 'foo', non un riferimento all'array print_first(\@a); # Mostrerà ARRAY(0x...) — riferimento all'intero array

Storia

In uno dei progetti, per modificare un hash globale, veniva chiamata la funzione così: update_hash(%global). All'interno si modificava $_[0]. Di conseguenza, veniva modificato solo un segmento locale dell'array di argomenti, e l'hash globale non veniva modificato. La soluzione corretta è stata passare un riferimento: update_hash(\%global).

Storia

Durante la scrittura di un framework API, le funzioni ricevevano molti argomenti nominati, utilizzando un hash. A volte veniva passato un array alla funzione (ma non un riferimento!), e gli argomenti venivano "mescolati", portando a confusione: myfunc(@arr, %opts). Si è scoperto che parte delle chiavi dell'hash veniva sovrascritta dai valori dell'array, e scoprire l'errore era difficile.

Storia

Durante l'implementazione di una ricerca ricorsiva in un albero, si voleva modificare gli elementi interni. Gli array venivano passati "così com'erano", non per riferimento. Venivano create copie e le modifiche non influenzavano il contesto esterno. Il problema è stato risolto sostituendo i passaggi con lo stile del riferimento.