2011-12-16 5 views
9

Questo è quello che ho:Come dovrei modificare il prototipo per consentire la costruzione di un hash dopo il coder?

use 5.14.0; 
use strict; 
use warnings; 

sub my_func(&$) { 
    my $coderef = shift; 
    my %attribs = @_; 
} 

Questo è quello che mi piacerebbe realizzare:

my_func { 
    print 1; 
} first_attrib => "1",second_attrib => "2"; 

Tuttavia, ricevo l'errore Too many arguments for main::my_func at x.pl line 12, near ""2";". Come dovrei modificare il prototipo, in modo che i parametri dopo il coderef vengano trasformati in un hash?

risposta

8

Se si modifica sub my_func(&$) a sub my_func(&%) il codice funzionerà.

Il problema è che first_attrib => "1",second_attrib => "2" non è un riferimento hash, ma un elenco. E come indicato da Friedo, un elenco può essere assegnato a un hash, anche se un elenco con un numero dispari di elementi potrebbe produrre risultati indesiderati e produrre un avviso con use warnings.

In alternativa è possibile modificare il codice per

sub my_func(&$) { 
    my $coderef = shift; 
    my ($attribs) = @_; 
} 

my_func { 
    print 1; 
} {first_attrib => "1",second_attrib => "2"}; 

per ottenere quello che ti sembra di volere.

Il motivo per cui è necessario avvolgere $attribs in Parens è che l'assegnazione di una matrice a uno scalare restituisce solo il numero di elementi nella matrice. A questo punto è @_ questa matrice:

({first_attrib => "1",second_attrib => "2"}) 

con rif hash come un unico elemento.

($attribs) = @_; 

dice Perl per creare un array anonimo con lo scalare $attribs come primo elemento, e assegnare elementi @_ alla matrice anonima, elemento per elemento, rendendo così $attribs punto al ref hash in @_.

+2

E 'più esatto dire che 'first_attrib => "1", second_attrib => "2"' è un * lista *, e una lista può essere assegnata ad un hash. – friedo

+0

@friedo: è vero. Grazie per la segnalazione. – flesk

3

È necessario realizzare gli argomenti in un sotto modulo Perl un elenco. È possibile utilizzare il primo elemento della lista di argomenti per la rifcodice e gli elementi rimanenti per formare un hash:

#!/usr/bin/env perl 

use 5.14.0; 
use strict; 
use warnings; 

sub my_func(&@) { 
    my $coderef = shift; 
    my %attribs = @_; 
    $coderef->() for keys %attribs; 
} 

my_func { 
    print 1; 
} first_attrib => "1",second_attrib => "2"; 
+2

++, il codice funzionerà con la chiamata come scritto, se il prototipo è appena cambiato in '(& @)'. – hobbs

+3

@hobbs: O '(&%)', che a mio parere sarebbe più intuitivo dato ciò che l'OP vuole ottenere. – flesk

Problemi correlati