我只是在玩弄在不使用引用的情况下修改 Perl 子例程中的参数的概念。我在数组的情况下试过这个:
sub test {
print "Trying to change ... \n";
$_[0] = "Third";
$_[1] = 100;
}
@a = ("First", 1, "Second", 2);
print "Before change : @a \n";
test(@a);
print "After change : @a \n";
输出:
Before change : First 1 Second 2
Trying to change ...
After change : Third 100 Second 2
换句话说,通过更改 @_
的值来更改数组的元素。
但是在散列的情况下做同样的事情并没有给出预期的行为:
sub test {
print "Trying to change ... \n";
$_[0] = "Third";
$_[1] = 100;
}
%h = ("First" => 1, "Second" => 2);
test(%h);
foreach ( keys %h ) {
print "$_\n";
}
输出:
Trying to change ...
Second
First
为什么这件事在这两种情况下不同?
最佳答案
你被误导了
Perl 散列键不是普通的 Perl 标量值——为了提高速度,它们存储为简单的 C 字符串,但散列值是 Perl 标量
在像 test(%h)
这样的调用中,Perl 从每个散列键字符串中创建一个临时的 Perl 标量并将它们与真实散列值标量一起传递
这意味着任何修改键字符串的尝试都只会更改临时标量,而不会反射(reflect)在散列中。但是您的代码确实改变了值
这是一个在子例程调用前后转储整个哈希的版本。您可以看到字符串 Third
已经丢失,但是 100
已分配给一个(随机)哈希值
use strict;
use warnings 'all';
use Data::Dump 'pp';
sub test {
$_[0] = "Third";
$_[1] = 100;
}
my %h = ("First" => 1, "Second" => 2);
printf "Before: %s\n", pp \%h;
test(%h);
printf "After: %s\n", pp \%h;
输出
Before: { First => 1, Second => 2 }
After: { First => 1, Second => 100 }
关于没有引用的 Perl 参数修改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37719086/