2013-10-18 14 views
7

vedere il codice qui sotto:

$scalar = 10; 

subroutine(\$scalar); 

sub subroutine { 
    my $subroutine_scalar = ${$_[0]}; #note you need the {} brackets, or this doesn't work! 
    print "$subroutine_scalar\n"; 
} 

Nel codice sopra potete vedere il commento scritto "nota hai bisogno delle parentesi {}, o questo non funziona! " . Si prega di spiegare il motivo per questo che non possiamo usare la stessa dichiarazione come:

my $subroutine_scalar = $$_[0]; 

cioè senza usare le parentesi graffe.

risposta

2

${ $x }[0] acquisisce il valore dell'elemento 0 nell'array a cui fa riferimento $x.

${ $x[0] } acquisisce il valore di scalare a cui fa riferimento l'elemento 0 dell'array @x.

>perl -E"$x=['def']; @x=\'abc'; say ${ $x }[0];" 
def 

>perl -E"$x=['def']; @x=\'abc'; say ${ $x[0] };" 
abc 

$$x[0] è l'abbreviazione di ${ $x }[0].

>perl -E"$x=['def']; @x=\'abc'; say $$x[0];" 
def 
1

Perché $$_[0] significa ${$_}[0].

Considerare questi due pezzi di codice che entrambi stampa 10:

sub subroutine1 { 
    my $scalar = 10; 
    my $ref_scalar = \$scalar; 
    my @array = ($ref_scalar); 
    my $subroutine_scalar = ${$array[0]}; 

    print "$subroutine_scalar\n"; 
} 

sub subroutine2 { 
    my @array = (10); 
    my $ref_array = \@array; 
    my $subroutine_scalar = $$ref_array[0]; 

    print "$subroutine_scalar\n"; 
} 

In subroutine1, @array è una matrice contenente il riferimento $scalar. Quindi il primo passo è quello di ottenere il primo elemento da $array[0], e quindi deferenza.

Mentre in subroutine2, @array è un vettore contenente un scalari 10, e $ ref_array è il suo riferimento. Quindi il primo passo è ottenere la matrice per $ref_array e quindi indicizzare la matrice.

2
my $subroutine_scalar = $$_[0]; 

è stessa

my $subroutine_scalar = $_->[0]; # $_ is array reference 

D'altra parte, ref

my $subroutine_scalar = ${$_[0]}; 

dereferenziazioni scalare per primo elemento di @_ matrice, e può essere scritto come

my ($sref) = @_; 
my $subroutine_scalar = ${$sref}; # or $$sref for short 
8

Molte persone hanno al pronto a dare le risposte corrette qui. Volevo aggiungere un esempio che ho trovato illuminante. È possibile leggere la documentazione in perldoc perlref per ulteriori informazioni.

Il tuo problema è uno di ambiguità, si hanno due operazioni $$ e [0] che lavorano sullo stesso identificatore _, e il risultato dipende da quale operazione viene eseguita per prima. Possiamo renderlo meno ambiguo utilizzando le parentesi graffe di supporto ${ ... }. $$_[0] potrebbe (per un essere umano comunque) significare:

  • ${$$_}[0] - dereference scalare $_, poi prendere il primo elemento.
  • ${$_[0]} - prendere l'elemento 0 dell'array @_ e dereferenziarlo.

Come si può vedere, questi due casi si riferiscono a completamente diverse variabili, @_ e $_.

Ovviamente, per Perl non è ambiguo, semplicemente otteniamo la prima opzione, poiché il dereferenziamento viene eseguito prima della ricerca della chiave. Abbiamo bisogno delle parentesi graffe di supporto per ignorare questo dereferenziamento, ed è per questo che il tuo esempio non "funziona" senza parentesi di supporto.

Si potrebbe considerare una funzionalità leggermente meno confusa per la subroutine. Invece di cercare di fare due cose contemporaneamente (ottenere l'argomento e dereferenziarlo), lo si può fare in due fasi:

sub foo { 
    my $n = shift; 
    print $$n; 
} 

Qui, prendiamo il primo argomento off @_ con shift, e poi dereferenziarlo. Pulito e semplice

Molto spesso, non si useranno i riferimenti alle variabili scalari, tuttavia. E in quei casi, è possibile utilizzare l'operatore freccia ->

my @array = (1,2,3); 
foo(\@array); 

sub foo { 
    my $aref = shift; 
    print $aref->[0]; 
} 

Trovo usando l'operatore freccia preferibile alla sintassi $$.