在$ _ [0],$ _ [1] .....等情况下解除引用

时间:2013-10-18 11:55:57

标签: perl

请参阅以下代码:

$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 个答案:

答案 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获取数组,然后索引数组。