2010-06-10 7 views
6

Non capisco come la funzione di lettura Perl ($ buf) sia in grado di modificare il contenuto della variabile $ buf. $ buf non è un riferimento, quindi il parametro è dato dalla copia (dalla mia conoscenza c/C++). Quindi, come mai la variabile $ buf è stata modificata nel chiamante?Qual è la magia dietro la funzione perl read() e il buffer che non è un riferimento?

È una variabile legata o qualcosa del genere? La documentazione in merito setbuf è anche abbastanza sfuggente e poco chiaro a me

# Example 1 
$buf=''; # It is a scalar, not a ref 
$bytes = $fh->read($buf); 
print $buf; # $buf was modified, what is the magic ? 

# Example 2 
sub read_it { 
    my $buf = shift; 
    return $fh->read($buf); 
} 
my $buf; 
$bytes = read_it($buf); 
print $buf; # As expected, this scope $buf was not modified 

risposta

11

Non è necessaria alcuna magia: tutte le subroutine perl sono call-by-alias, se lo si desidera. Quoth perlsub:

L'array @_ è una matrice locale, ma i suoi elementi sono alias per i parametri scalari reali. In particolare, se un elemento $ _ [0] viene aggiornato, l'argomento corrispondente viene aggiornato (o si verifica un errore se non è aggiornabile).

Ad esempio:

sub increment { 
    $_[0] += 1; 
} 

my $i = 0; 
increment($i); # now $i == 1 

Nella "Esempio 2", tuoi read_it sub copie il primo elemento del @_ al lessico $buf, quale copia viene poi modificato "in loco" dal chiamare allo read(). Passano in $_[0] invece di copiare, e vedere cosa succede:

sub read_this { 
    $fh->read($_[0]); # will modify caller's variable 
} 
sub read_that { 
    $fh->read(shift); # so will this... 
} 
+0

Grazie mille per il puntatore al documento pertinente, e il tuo trucco funziona, grazie mille –

0

read() è una funzione built-in, e quindi può fare la magia. È possibile eseguire qualcosa di simile con le proprie funzioni, anche se, dichiarando un function prototype:

sub myread(\$) { ... } 

La dichiarazione tesi \$ significa che l'argomento è implicitamente passato come riferimento.

L'unica magia nel read integrato è che funziona anche quando viene chiamato indirettamente o come un metodo di filehandle, che non funziona per le normali funzioni.

+3

non hai bisogno di un prototipo o di passaggio per riferimento esplicito al fine di modificare una variabile passata a una subroutine: 'sub pippo {$ _ [ 0] ++} '. – FMc

+0

+1 Questo non è il punto giusto per la domanda dell'OP, ma i prototipi ei riferimenti * in buona fede * perl (non i riferimenti simbolici) sono importanti da sapere in questo dominio. – pilcrow

+0

@ FM, buona presa. Ho sempre dimenticato che '@ _' può essere usato in questo modo. –