Question

Je sais que le passage d'un scalaire à un sous est en fait passer la référence, mais depuis que je suis nouveau à perl je encore fait le test suivant:

#!/usr/bin/perl
$i = 2;
subr(\$i);
sub subr{
    print $_[0]."\n";
    print $$_[0]."\n";
}

Je pensais que la première ligne va imprimer une adresse et la deuxième ligne va donner de retour le nombre, mais la seconde est une ligne blanche. Je fait remarquer par quelqu'un d'autre pour le faire: ${$_[0]} et imprime le nombre. Mais elle ne savait pas la raison pour laquelle, sans {} il ne fonctionne pas et pourquoi il travaille avec {}. Alors qu'est-ce qui est arrivé?

Était-ce utile?

La solution

Il est parce que votre deuxième déclaration d'impression équivaut à le faire ...

my $x = $$_; print $x[0];

Quand est ce que vous voulez

my $x = $_[0]; print $$x;

En d'autres termes, le de-référence se produit avant l'indice de tableau est évalué.

Lorsque vous ajoutez ces papillotes wurlies, il raconte comment perl d'interpréter l'expression que vous voulez; il évaluera d'abord $_[0], puis de référence pour obtenir la valeur.

Autres conseils

Il est une chose d'ordre de l'évaluation.

  $$_[0] is evaluated as {$$_}[0]

Ceci est l'élément 0e de la référence de la variable scalaire $ _. Il prend la référence en premier et ensuite essayer de trouver l'élément 0e de celui-ci.

  ${$_[0]}

Ceci est une référence à l'élément 0e du tableau @_. Il est l'élément 0e trouver d'abord puis en prenant une référence de cela.

Si vous définissez use strict et use warnings en haut de votre code, vous verrez beaucoup d'avertissements sur les valeurs non définies à partir de votre première tentative.

$$_[0] est comme $foo[0], avec seulement $ _ à la place du nom du tableau. Cela signifie $ _ est considéré comme une référence de tableau, et l'expression ne comprend pas le $_[0] de référence scalaire du tout. $_->[0] est équivalente, en utilisant la syntaxe alternative de ->. Syntaxe pour déréférencement peut sembler arbitraire et difficile de se souvenir, mais il y a le sens et l'ordre sous-jacent; une très bonne présentation, il est à http://perlmonks.org/?node=References+quick + référence .

Vous ne devez pas passer une référence à $i. La notation est un $_[0] alias pour $i lorsque vous invoquez comme subr( $i ).

use strict;
use warnings;
use Test::More tests => 2;

sub subr{ $_[0]++ } # messing with exactly what was passed first
my $i=2;
is( $i, 2, q[$i == 2] );
subr($i);
is( $i, 3, q[$i == 3] );

Un autre exemple est la suivante:

use strict;
use warnings;
use Test::More tests => 6;
use Test::Exception;

sub subr{ $_[0]++ }
my $i=2;
is( $i, 2, q[$i == 2] );
subr($i);
is( $i, 3, q[$i == 3] );

sub subr2 { $_[0] .= 'x'; }
dies_ok { subr2( 'lit' ); } 'subr2 *dies* trying to modify a literal';
lives_ok { 
    my $s = 'lit';
    subr2( $s );
    is( $s, 'litx', q[$s eq 'litx'] );
    subr2(( my $s2 = 'lit' ));
    is( $s2, 'litx', q[$s2 eq 'litx'] );
} 'subr2 lives with heap variables';

Sortie:

ok 1 - $i == 2
ok 2 - $i == 3
ok 3 - subr2 *dies* trying to modify a literal
ok 4 - $s eq 'litx'
ok 5 - $s2 eq 'litx'
ok 6 - subr2 lives with heap variables
1..6
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top