请参阅以下代码:
$scalar = 10;
subroutine(\$scalar);
sub subroutine {
my $subroutine_scalar = ${$_[0]}; #note you need the {} brackets, or this doesn't work!
print "$subroutine_scalar\n";
}
在上面的代码中,您可以看到写下的评论“请注意您需要{}括号,否则这不起作用!” 。请解释为什么我们不能使用相同的声明:
my $subroutine_scalar = $$_[0];
即。不使用大括号。
答案 0 :(得分:8)
很多人已经在这里给出了正确答案。我想添加一个我发现有启发性的例子。您可以阅读perldoc perlref中的文档以获取更多信息。
您的问题不明确,您有两个操作$$
和[0]
处理相同的标识符_
,结果取决于首先执行的操作。我们可以通过使用支撑花括号${ ... }
来减少它的含糊。 $$_[0]
可能(对于人类而言)可能意味着:
${$$_}[0]
- 取消引用标量$_
,然后取其第一个元素。 ${$_[0]}
- 获取数组0
的元素@_
并取消引用它。 如您所见,这两种情况指的是完全不同的变量@_
和$_
。
当然,对于Perl来说它并不含糊,我们只是得到第一个选项,因为在键查找之前执行解除引用。我们需要支持花括号来覆盖这种解除引用,这就是为什么你的例子没有支持括号就“工作”的原因。
您可能会认为子程序的功能稍微有些混乱。你可以分两个阶段来做,而不是试图一次做两件事(得到论证并取消引用它):
sub foo {
my $n = shift;
print $$n;
}
在这里,我们将@_
的第一个参数与shift
取消,然后取消引用它。干净简单。
但是,大多数情况下,您不会使用对标量变量的引用。在这些情况下,您可以使用箭头操作符->
my @array = (1,2,3);
foo(\@array);
sub foo {
my $aref = shift;
print $aref->[0];
}
我发现使用箭头运算符比$$
语法更可取。
答案 1 :(得分:2)
${ $x }[0]
获取$x
引用的数组中元素0的值。
${ $x[0] }
获取数组@x
的元素0引用的标量值。
>perl -E"$x=['def']; @x=\'abc'; say ${ $x }[0];"
def
>perl -E"$x=['def']; @x=\'abc'; say ${ $x[0] };"
abc
$$x[0]
是${ $x }[0]
的缩写。
>perl -E"$x=['def']; @x=\'abc'; say $$x[0];"
def
答案 2 :(得分:2)
my $subroutine_scalar = $$_[0];
与
相同my $subroutine_scalar = $_->[0]; # $_ is array reference
另一方面,
my $subroutine_scalar = ${$_[0]};
取消引用@_
数组的第一个元素的标量引用,可以写成
my ($sref) = @_;
my $subroutine_scalar = ${$sref}; # or $$sref for short
答案 3 :(得分:1)
因为$$_[0]
表示${$_}[0]
。
考虑这两段代码,它们都打印10
:
sub subroutine1 {
my $scalar = 10;
my $ref_scalar = \$scalar;
my @array = ($ref_scalar);
my $subroutine_scalar = ${$array[0]};
print "$subroutine_scalar\n";
}
sub subroutine2 {
my @array = (10);
my $ref_array = \@array;
my $subroutine_scalar = $$ref_array[0];
print "$subroutine_scalar\n";
}
在subroutine1
中,@array
是一个包含$scalar
引用的数组。因此,第一步是通过$array[0]
获取第一个元素,然后将其推迟。
在subroutine2
中,@array
是包含标量10
的数组,$ ref_array是其引用。所以第一步是通过$ref_array
获取数组,然后索引数组。