2010-03-20 21 views
5

Sono stato con Perl per qualche tempo, ma oggi mi sono imbattuto in questo codice:

sub function1($$) 
{ 
    //snip 
} 

Cosa significa questo in Perl?

risposta

15

È una funzione con un prototype che accetta due argomenti scalari.

Ci sono forti argomenti per non utilizzare in realtà i prototipi Perl in generale - come indicato nei commenti seguenti. L'argomento più forte è probabilmente:

C'è una discussione su StackOverflow dal 2008:

C'è una possibile sostituzione nel modulo MooseX::Method::Signatures.

+0

grazie !! ho quasi capito. Perché è necessario, qualche tipo di controllo di tipo e numero sui parametri, vero? – sud03r

+0

Perl non richiede prototipi; sono del tutto opzionali. Tuttavia, proprio come nel codice C, la fornitura di prototipi può risolvere alcuni errori che altrimenti rimarranno non rilevati. Nel complesso, non sono usati molto spesso, secondo la mia esperienza - in parte perché sono un'aggiunta tardiva alla lingua, e in parte perché i programmatori Perl sfruttano (nel bene, nel complesso) la flessibilità dei sottotitoli Perl senza prototipi e in parte perché le persone non amano evitare errori automaticamente (sembrano preferire trovarli nel modo più duro). –

+3

I prototipi non sono usati nel moderno Perl perché sono guasti. Quanto rotto? Ecco una domanda recente che illustra solo uno dei loro numerosi problemi: http://stackoverflow.com/questions/2485106/why-do-printf-and-sprintf-behave-differently I prototipi non sono utilizzati per il controllo dei tipi, sono suggerimenti per il compilatore e Perl * costringerà gli argomenti del chiamante per adattarsi al prototipo * anche se sono sbagliati. – rjh

11

Come l'altra risposta menziona, lo $$ dichiara un prototipo. Ciò che l'altra risposta non dice è a cosa servono i prototipi. Non sono per la convalida dell'input, sono suggerimenti per il parser.

Immaginate di avere due funzioni dichiarato come:

sub foo($) { ... } 
sub bar($$) { ... } 

Ora, quando si scrive qualcosa di ambiguo, come:

foo bar 1, 2 

Perl sa dove mettere le parentesi; la barra richiede due arg, quindi consuma i due più vicini. foo prende uno arg, così prende il risultato di bar e due args:

foo(bar(1,2)) 

altro esempio:

bar foo 2, 3 

Lo stesso dicasi; foo prende uno arg, quindi diventa il 2. bar prende due argomenti, quindi diventa foo(2) e 3:

bar(foo(2),3) 

Questa è una parte abbastanza importante di Perl, in modo che respinge come "non usare mai" si sta facendo un cattivo servizio. Quasi tutte le funzioni interne utilizzano i prototipi, quindi comprendendo come funzionano nel proprio codice, è possibile ottenere una migliore comprensione di come vengono utilizzati dai builtin. Quindi puoi evitare parentesi non necessarie, il che rende il codice più gradevole.

Infine, un anti-modello vi guardia contro:

package Class; 
sub new ($$) { bless $_[1] } 
sub method ($) { $_[0]->{whatever} } 

Quando si sta chiamando codice come metodi (Class->method o $instance->method), il controllo di prototipo è completamente priva di senso. Se il tuo codice può essere chiamato solo come metodo, aggiungere un prototipo è sbagliato. Ho visto alcuni moduli popolari che fanno questo (ciao, XML::Compile), ma è sbagliato, quindi non farlo.Se si desidera documentare quanti args passare, come su:

sub foo { 
    my ($self, $a, $b) = @_; # $a and $b are the bars to fooify 
    .... 

o

use MooseX::Method::Signatures; 

method foo(Bar $a, Bar $b) { # fooify the bars 
    .... 

differenza foo($$), questi sono significativo e leggibile.