Cosa significa la funzione “sottofunzione ($$)”?

Ho usato Perl per un po ‘di tempo, ma oggi ho trovato questo codice:

sub function1($$) { //snip } 

Cosa significa questo in Perl?

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


Ci sono forti argomentazioni per non utilizzare in realtà i prototipi Perl in generale – come notato nei commenti seguenti. L’argomento più forte è probabilmente:

  • Molto più di tutto quello che hai sempre voluto sapere sui prototipi in Perl

C’è una discussione su StackOverflow del 2008:

  • SO 297034

C’è una ansible sostituzione nel modulo MooseX :: Method :: Signatures .

Come menziona l’altra risposta, il $$ 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.

Immagina di avere due funzioni dichiarate come:

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

Ora quando scrivi qualcosa di ambiguo, come:

 foo bar 1, 2 

Perl sa dove mettere i paren; la barra richiede due arg, quindi consuma i due più vicini. pippo prende un arg, quindi prende il risultato della barra e i due argomenti:

 foo(bar(1,2)) 

Un altro esempio:

 bar foo 2, 3 

Lo stesso vale; pippo prende un arg, quindi ottiene 2. la barra prende due args, quindi ottiene foo(2) e 3:

 bar(foo(2),3) 

Questa è una parte piuttosto importante di Perl, quindi respingerlo come “non usare mai” ti sta rendendo un disservizio. Quasi tutte le funzioni interne utilizzano i prototipi, quindi comprendendo come funzionano nel proprio codice, è ansible 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-pattern ti avvertirà contro:

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

Quando si chiama codice come metodo ( Class->method o Class->method $instance->method ), il controllo del prototipo è completamente privo di significato. 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 vuoi documentare il numero di argomenti da passare, che ne dici di:

 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 .... 

A differenza di foo($$) , questi sono significativi e leggibili.