7

请看下面的代码:

$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];

即不使用大括号。

4

4 回答 4

9

很多人已经在这里给出了正确的答案。我想添加一个我觉得很有启发性的例子。您可以阅读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];
}

我发现使用箭头运算符比$$语法更可取。

于 2013-10-18T13:36:18.337 回答
2

${ $x }[0]获取 .引用的数组中元素 0 的值$x

${ $x[0] }获取数组的元素 0 引用的标量值@x

>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
于 2013-10-18T12:05:20.140 回答
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
于 2013-10-18T12:26:40.847 回答
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],然后尊重它。

而 insubroutine2@array一个包含标量的数组10, $ref_array 是它的引用。所以第一步是通过 获取数组$ref_array,然后对数组进行索引。

于 2013-10-18T12:13:40.570 回答