我知道将标量传递给子实际上是传递引用,但由于我是 perl 新手,我仍然做了以下测试:
#!/usr/bin/perl
$i = 2;
subr(\$i);
sub subr{
print $_[0]."\n";
print $$_[0]."\n";
}
我以为第一行会打印一个地址,第二行会返回数字,但第二行是空行。我被其他人指出要这样做:${$_[0]}
它会打印数字。但她不知道没有 {} 无法正常工作的原因以及与 {} 一起工作的原因。那么发生了什么?
这是因为你的第二个打印语句相当于这样做......
my $x = $$_; print $x[0];
当你想要的是
my $x = $_[0]; print $$x;
换句话说,取消引用发生在计算数组下标之前。
当您添加这些 curl-wurlies 时,它会告诉 perl 如何根据需要解释表达式;它将$_[0]
首先评估,然后取消引用以获取值。
这是一个评估顺序的事情。
$$_[0] is evaluated as {$$_}[0]
这是标量变量 $_ 的引用的第 0 个元素。它首先获取参考,然后尝试找到它的第 0 个元素。
${$_[0]}
这是对数组 @_ 的第 0 个元素的引用。它首先找到第 0 个元素,然后引用它。
如果您在代码顶部设置use strict
和,您将在第一次尝试时看到大量关于未定义值的警告。use warnings
$$_[0]
就像$foo[0]
,仅用 $_ 代替数组名称。这意味着 $_ 被视为数组引用,并且表达式根本不涉及标量引用$_[0]
。 $_->[0]
是等效的,使用替代->
语法。取消引用的语法可能看起来随意且难以记住,但有潜在的意义和顺序;在http://perlmonks.org/?node=References+quick+reference上有一个很好的介绍。
您不必传递对$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