我知道将标量传递给sub实际上是通过引用,但由于我是perl的新手,我仍然进行了以下测试:
#!/usr/bin/perl
$i = 2;
subr(\$i);
sub subr{
print $_[0]."\n";
print $$_[0]."\n";
}
我认为第一行将打印一个地址,第二行将返回该数字,但第二行是一个空行。我被其他人指出要执行此操作:${$_[0]}
并打印数字。但她不知道为什么没有{}它不起作用以及为什么它与{}合作。那发生了什么事?
答案 0 :(得分:14)
这是因为你的第二个印刷声明等同于这样做......
my $x = $$_; print $x[0];
当你想要的是什么
my $x = $_[0]; print $$x;
换句话说,取消引用发生在评估数组下标之前。
当你添加那些curl-wurlies时,它告诉perl如何解释你想要的表达式;它将首先评估$_[0]
,然后取消引用以获取值。
答案 1 :(得分:8)
这是一个评估顺序。
$$_[0] is evaluated as {$$_}[0]
这是标量变量$ _的引用的第0个元素。它首先获取引用,然后尝试找到它的第0个元素。
${$_[0]}
这是对数组@_的第0个元素的引用。它首先找到第0个元素,然后参考它。
如果您在代码顶部设置use strict
和use warnings
,则会在第一次尝试时看到大量有关未定义值的警告。
答案 2 :(得分:3)
$$_[0]
与$foo[0]
类似,仅使用$ _代替数组名称。这意味着$ _被视为数组引用,表达式根本不涉及标量引用$_[0]
。 $_->[0]
是等效的,使用备用->
语法。解除引用的语法可能看似随意且难以记住,但存在潜在的感觉和顺序;一个非常好的演示文稿是http://perlmonks.org/?node=References+quick+reference。
答案 3 :(得分:1)
您不必传递对$i
的引用。当您$_[0]
将$i
作为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] );
是别名。
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';
另一个例子是:
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
输出:
{{1}}