问题
I've read that perl uses call-by-reference when executing subrutines. I made a simple piece of code to check this property, but it behaves like if perl was call-by-value:
$x=50;
$y=70;
sub interchange {
($x1, $y1) = @_;
$z1 = $x1;
$x1 = $y1;
$y1 = $z1;
print "x1:$x1 y1:$y1\n";
}
&interchange ($x, $y);
print "x:$x y:$y\n";
This produces the following output:
$ perl example.pl
x1:70 y1:50
x:50 y:70
If arguments were treated in a call-by-reference way, shouldn't x be equal to x1 and y equal to y1?
回答1:
To modify the values outside of the sub, you would have to modify the values of @_
.
The following sub interchange
does modify the values:
sub interchange {
($x1, $y1) = @_; # this line copies the values to 2 new variables
$z1 = $x1;
$x1 = $y1;
$y1 = $z1;
$_[0] = $x1; # this line added to change value outside sub
$_[1] = $y1; # this line added to change value outside sub
print "x1:$x1 y1:$y1\n";
}
This gives the output:
x1:70 y1:50
x:70 y:50
More info here: http://www.cs.cf.ac.uk/Dave/PERL/node51.html
But, to quote the article:
You can see that the function was able to affect the @array variable in the main program. Generally, this is considered bad programming practice because it does not isolate what the function does from the rest of the program.
回答2:
Perl is always definitely call by reference. You're statement ($x1, $y1) = @_
is copying the original argument values, since @_ holds aliases to the original parameters.
From perlsub manpage:
Any arguments passed in show up in the array @_ . Therefore, if you called a function with two arguments, those would be stored in $[0] and $[1] . The array @_ is a local array, but its elements are aliases for the actual scalar parameters. In particular, if an element $_[0] is updated, the corresponding argument is updated (or an error occurs if it is not updatable).
回答3:
I'm just starting with Perl as well, and I believe you're misunderstanding just what you're passing to the subroutine. When you pass $x and $y you are passing the scalars $x and $y are set to. You need to explicitly pass a reference, which also happens to be a scalar (being the only thing are ever allowed to pass to subroutines). I understand where you're coming from in thinking things are call-by-reference since for arrays and hashes, since you need to pass references to those.
This code should do what you're looking for:
#!/usr/bin/perl
$x=50;
$y=70;
sub interchange {
($x1, $y1) = @_;
$z1 = $$x1; # Dereferencing $x1
$$x1 = $$y1; # Dereferencing $x1 and $y1
$$y1 = $z1; # Dereferencing $y1
print "x1:$$x1 y1:$$y1\n";
}
&interchange (\$x, \$y); # Passing references to $x and $y, not their values
print "x:$x y:$y\n";
I pass in references to $x and $y using \$x and \$y. Then, I use $$x and $$y to dereference them within the subroutine.
来源:https://stackoverflow.com/questions/24063638/if-perl-is-call-by-reference-why-does-this-happen