perl参考澄清需要

时间:2017-08-16 17:15:42

标签: perl reference

直接来自https://perldoc.perl.org/perlref.html

我不明白下面

 $$hashref{"KEY"}   = "VALUE";       # CASE 0
 ${$hashref}{"KEY"} = "VALUE";       # CASE 1
 ${$hashref{"KEY"}} = "VALUE";       # CASE 2
 ${$hashref->{"KEY"}} = "VALUE";     # CASE 3

案例1和案例2之间有什么区别?

我在想${}内的任何内容都是指向某个地址的指针,所以它就像

my $hashref = \%hash;

${$hashref}{"KEY"}真的是$$hashref{"KEY"},这是解除引用\%hash并查找"KEY"

${$hashref->{"KEY"}} ..我想是......?我认为规则是最接近左边的绑定所以我认为这也变成了$$hashref->{"KEY"}。与${$hashref}{'KEY'}相同。我错了吗?

3 个答案:

答案 0 :(得分:1)

案例0和1是等效的,您已正确理解这些。

案例2有点微妙:

${$hashref{"KEY"}} = "VALUE";

首先,执行$hashref{"KEY"},在名为"KEY"的哈希变量中查找%hashref。尽管它的名字是哈希,而不是哈希引用!这将返回该哈希值。

接下来,我们将散列中的值取消引用为标量引用:${ ... }

最后,我们将"VALUE"分配给标量参考目标。

案例3类似,但实际上使用哈希引用。

如果我们重写案例2和案例3,他们的关系可能会更清楚:

{ # Case 2
  my %hash;
  ${ $hash{"KEY"} } = "VALUE";
}

{ # Case 3
  my %hash;
  my $hashref = \%hash;
  ${ $hashref->{"KEY"} } = "VALUE";
}

补充说明:

  • ${ … }解除引用运算符不会最接近左边,包含将被解除引用的值。如果引用是正常的标量变量,$$foo形式是${ … }解除引用运算符的缩写形式,而不是更复杂的表达式。这不仅适用于标量引用,还适用于数组引用(@{ … }@$foo)以及散列引用(%{ … }%$foo)。

  • 取消引用运算符的sigil($%@)不是引用的类型,而是取决于我们是否正在访问引用目标中的一个或多个值。

    当我们访问哈希%hash中的单个值时,这看起来像$hash{"KEY"}

    当我们访问$hashref中的单个值时,这看起来像$hashref->{"KEY"}${$hashref}{"KEY"}$$hashref{"KEY"}

    尽管有$,但这里没有标量参考。标量解除引用运算符${ … }本质上是与哈希引用下标运算符${ … }{ … }不同的运算符。

  • 表达式$$foo->{"KEY"}具有对哈希引用的标量引用! Firs将标量引用$foo解除引用$$foo到散列引用,其中访问值…->{"KEY"}

答案 1 :(得分:0)

情况0和1之间的区别在于,在情况1中,可以在${}内使用代码块,其返回hashref。有些东西在没有{}的情况下工作,就像案例1中的具体示例一样,但有些东西不能。它说elsewhere in perlref

  

在您将标识符(或标识符链)作为变量或子例程名称的一部分放置的任何地方,您可以使用包含正确类型的引用的简单标量变量替换标识符
  ...
  比简单标量变量更复杂的必须使用下面的方法2或3。
  ...
  在您将标识符(或标识符链)作为变量或子例程名称的一部分放置的任何地方,您可以使用BLOCK替换标识符,返回正确类型的引用

(强调我的)

一个例子

sub get_hr { return { a => 1, b => 2 } }

say ${ get_hr() }{a}

可能会有点过分(并且不适合生产),但希望能够传达它。

答案by amonby ikegami中提供了许多其他说明。

另见Using references in perlreftutCaveats on precedence in perldsc

答案 2 :(得分:0)

  • $NAME(例如$foo)是一个标量变量。
  • $BLOCK(例如${ $ref })是一个标量变量(通过引用)。
  • $$NAME(例如$$ref)是${ $NAME }的缩写(例如${ $ref })。

类似地,

  • $NAME{EXPR}(例如$foo{bar})是一个哈希元素。
  • $BLOCK{EXPR}(例如${ $ref }{bar})是一个哈希元素(通过引用)。
  • $$NAME{EXPR}(例如$$ref{bar})是${ $NAME }{EXPR}的缩写(例如${ $ref }{bar})。

所以,

  • $$hash_ref{"KEY"}${ $hashref }{"KEY"}
  • 的缩写
  • ${ $hash_ref }{"KEY"}是一个哈希元素。
    $hashref是对哈希的引用。
  • ${ $hash{"KEY"} }是一个标量变量。
    $hash{"KEY"}是对标量的引用。
    %hash是一个哈希值。
  • ${ $hash_ref->{"KEY"} }是一个标量变量。
    $hash_ref->{"KEY"}是写$$hash_ref{"KEY"}的好方法。)
    $hash_ref->{"KEY"}是对标量。
    $hash_ref是对哈希的引用。