2010-06-10 19 views
6

Je n'arrive pas à comprendre comment la fonction Perl read ($ buf) est capable de modifier le contenu de la variable $ buf. $ buf n'est pas une référence, donc le paramètre est donné par copy (à partir de mes connaissances c/C++). Alors, comment se fait-il que la variable $ buf soit modifiée dans l'appelant?Quelle est la magie derrière perl read() fonction et le tampon qui n'est pas un ref?

Est-ce une variable de lien ou quelque chose? La documentation C à propos setbuf est également tout à fait insaisissable et pas clair pour moi

# 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 

Répondre

11

Aucune magie n'est nécessaire - tous les sous-programmes perl sont appelés par alias, si vous voulez. Quoth perlsub:

Le tableau @_ est un tableau local, mais ses éléments sont des alias pour les paramètres scalaires réels. En particulier, si un élément $ _ [0] est mis à jour, l'argument correspondant est mis à jour (ou une erreur se produit s'il n'est pas modifiable).

Par exemple:

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

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

Dans votre "Exemple 2", vos read_it sous copies le premier élément de @_ au $buf lexical, qui copie est ensuite modifiée "en place" par la appelez le read(). Passez dans $_[0] au lieu de copier, et de voir ce qui se passe:

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

Merci beaucoup pour le pointeur vers le doc pertinent, et votre tour fonctionne, merci beaucoup –

0

read() est une fonction intégrée, et peut donc faire de la magie. Vous pouvez accomplir quelque chose de similaire avec vos propres fonctions, bien que, en déclarant un function prototype:

sub myread(\$) { ... } 

La déclaration argument \$ signifie que l'argument est implicitement passé comme une référence.

La seule magie dans le read intégré est qu'il fonctionne même lorsqu'il est appelé indirectement ou en tant que méthode de gestion de fichier, ce qui ne fonctionne pas pour les fonctions normales.

+3

Vous n'avez pas besoin d'un prototype ou le passage par référence explicite afin de modifier une variable passée à un sous-programme: 'sous foo {$ _ [ 0] ++} '. – FMc

+0

+1 Ce n'est pas tout à fait le point pour la question de l'OP, mais les prototypes et les références perl * bona fide * (et non les références symboliques) sont importants à connaître dans ce domaine. – pilcrow

+0

@FM, bonne prise. J'oublie toujours que '@ _' peut être utilisé de cette façon. –