Quando dovrei usare & per chiamare una subroutine Perl?

Ho sentito che le persone non dovrebbero usare & chiamare i sottotitoli Perl, cioè:

 function($a,$b,...); # opposed to &function($a,$b,...); 

So per certo che l’elenco degli argomenti diventa facoltativo, ma quali sono alcuni casi in cui è opportuno utilizzare il & e i casi in cui non si dovrebbe assolutamente utilizzarlo?

Inoltre, come entra in gioco l’aumento delle prestazioni quando ometti il & ?

IMO, l’unica volta che c’è qualche ragione per usare & è se stai ottenendo o chiamando un coder, come:

 sub foo() { print "hi\n"; } my $x = \&foo; &$x(); 

L’ora principale che è ansible utilizzare non dovrebbe assolutamente nella maggior parte dei casi quando si chiama un sottotitolo che ha un prototipo che specifica un comportamento di chiamata non predefinito. Ciò che intendo è che alcuni prototipi consentono la reinterpretazione dell’elenco degli argomenti, ad esempio la conversione di @array e delle specifiche di %hash ai riferimenti. Quindi il sub si aspetterà che tali reinterpretazioni si siano verificate e, a meno che non si decida a quale lunghezza sia necessaria per imitarle a mano, il sottotitolo otterrà input selvaggiamente diversi da quelli che si aspetta.

Penso che la maggior parte delle persone stia cercando di dirti che stai ancora scrivendo in stile Perl 4, e ora abbiamo una cosa molto più bella, più bella, chiamata Perl 5.

Per quanto riguarda le prestazioni, ci sono vari modi in cui Perl ottimizza le sub-chiamate che & sconfigge, con uno dei principali che è l’inlining delle costanti.

C’è anche una circostanza in cui l’utilizzo & fornisce un vantaggio in termini di prestazioni: se si sta inoltrando una chiamata secondaria con foo(@_) . L’uso di &foo è infinitamente più veloce di foo(@_) . Non lo consiglierei a meno che tu non abbia definitivamente trovato dal profiling che hai bisogno di quella micro-ottimizzazione.

Sono un abusato frequente di & , ma soprattutto perché sto facendo cose strane all’interfaccia. Se non hai bisogno di una di queste situazioni, non utilizzare il & . La maggior parte di questi sono solo per accedere a una definizione di subroutine, non chiamare una subroutine. È tutto in perlsub .

  1. Prendendo un riferimento a una subroutine nominata. Questa è probabilmente l’unica situazione comune per la maggior parte dei Perlers:

      my $sub = \&foo; 
  2. Allo stesso modo, assegnando a un typeglob, che consente di chiamare la subroutine con un nome diverso:

      *bar = \&foo; 
  3. Verificare che una subroutine sia definita, come si potrebbe fare nelle suite di test:

      if( defined &foo ) { ... } 
  4. Rimozione di una definizione di subroutine, che non dovrebbe essere comune:

      undef &foo; 
  5. Fornire una subroutine di dispatcher il cui unico compito è scegliere la subroutine giusta da chiamare. Questa è l’unica situazione che uso & per chiamare una subroutine, e quando mi aspetto di chiamare il dispatcher molte, molte volte e ho bisogno di spremere un po ‘di prestazioni dall’operazione:

      sub figure_it_out_for_me { # all of these re-use the current @_ if( ...some condition... ) { &foo } elsif( ...some other... ) { &bar } else { &default } } 
  6. Per saltare in un’altra subroutine usando lo stack di argomenti corrente (e sostituendo la subroutine corrente nello stack di chiamate), un’operazione unrare in dispatching, specialmente in AUTOLOAD :

      goto ⊂ 
  7. Chiama una subroutine che hai nominato dopo un built-in Perl. Il & dà sempre quello definito dall’utente. Ecco perché lo insegniamo in Learning Perl . Non lo vuoi fare normalmente, ma è una delle caratteristiche di & .

Ci sono alcuni posti in cui potresti usarli, ma ci sono modi migliori:

  1. Per chiamare una subroutine con lo stesso nome di un built-in Perl. Basta non avere subroutine con lo stesso nome di un built-in Perl. Controlla perlfunc per vedere l’elenco dei nomi predefiniti che non dovresti usare.

  2. Per disabilitare i prototipi. Se non sai cosa significa o perché lo vuoi, non utilizzare il & . Qualche codice di magia nera potrebbe averne bisogno, ma in quei casi probabilmente sai cosa stai facendo.

  3. Per dereferenziare ed eseguire un riferimento alla subroutine. Basta usare la notazione -> .

La forma & subroutine () disabilita la verifica del prototipo. Questo può o non può essere quello che vuoi.

http://www.perl.com/doc/manual/html/pod/perlsub.html#Prototypes

I prototipi ti consentono di specificare i numeri e i tipi dei tuoi argomenti di subroutine e di farli controllare in fase di compilazione. Questo può fornire un’utile assistenza diagnostica.

I prototipi non si applicano alle chiamate ai metodi o alle chiamate effettuate nello stile vecchio stile utilizzando il prefisso &.

& È necessario fare riferimento o dereferenziare una subroutine o codice di riferimento

per esempio

 sub foo { # a subroutine } my $subref = \&foo; # take a reference to the subroutine &$subref(@args); # make a subroutine call using the reference. my $anon_func = sub { ... }; # anonymous code reference &$anon_func(); # called like this 

Protypes non è applicabile anche ai riferimenti alle subroutine.

La forma & subroutine è anche usata nella cosiddetta forma goto magica .

L’espressione goto &subroutine sostituisce il contesto di chiamata corrente con una chiamata alla subroutine denominata, utilizzando il valore corrente di @_.

In sostanza, è ansible passare completamente una chiamata a una subroutine con una chiamata a quella denominata. Questo è comunemente visto nei blocchi AUTOLOAD, dove è ansible effettuare una chiamata di subroutine differita, magari con qualche modifica a @_, ma guarda al programma interamente come se fosse una chiamata al sub chiamato.

per esempio

 sub AUTOLOAD { ... push @_, @extra_args; # add more arguments onto the parameter list goto &subroutine ; # change call another subroutine, as if we were never here } 

}

Potenzialmente questo potrebbe essere utile per l’ eliminazione della coda , suppongo.

vedere la spiegazione dettagliata di questa tecnica qui

Ho letto gli argomenti contro l’uso di “&”, ma lo uso quasi sempre. Mi fa risparmiare troppo tempo per non farlo. Trascorro una frazione molto grande del mio tempo di codifica Perl cercando quali parti del codice chiamano una funzione particolare. Con un leader e, posso cercare e trovarli all’istante. Senza leader e, ottengo la definizione di funzione, commenti e istruzioni di debug, di solito triplicando la quantità di codice che devo ispezionare per trovare quello che sto cercando.

La cosa principale che non usa ‘&’ compra te è che ti permette di usare i prototipi di funzione. Ma i prototipi di funzione Perl possono creare errori tutte le volte che li prevengono, perché prenderanno la tua lista di argomenti e la reinterpreteranno in modi che potresti non aspettarti, in modo che la tua chiamata di funzione non superi più gli argomenti che dice letteralmente di fare.