【问题标题】:Why does Perl treat a hash element as list context at declaration?为什么 Perl 在声明时将哈希元素视为列表上下文?
【发布时间】:2015-06-03 04:52:11
【问题描述】:

鉴于此代码:

#!/usr/bin/perl -w

use strict;
use warnings;

sub foo {
    return wantarray ? () : "value1";
}

my $hash = {
    key1 => foo(),
    key2 => 'value2'
};

use Data::Dumper;
print Dumper($hash);

我得到以下输出:

$VAR1 = {
  'key1' => 'key2',
  'value2' => undef
};

当我期望时:

$VAR1 = {
  'key1' => 'value1',
  'key2' => 'value2'
};

我知道散列是一种偶数大小的数组(正如我得到的“散列分配中的奇数个元素”警告所证明的那样),但散列元素只能是标量,为什么编译器会给它数组上下文?

我在直接分配给哈希时使用 CGI 模块的 param 函数发现了这一点。上面的 foo() 函数是对 CGI::param('mistyped_url_param') 的调用,它返回一个空数组,破坏(旋转?)哈希结构。

【问题讨论】:

  • 一个不相关的点:你不再需要 shebang 行中的'-w','使用警告'取代了它。 (虽然 -w 为所有加载的包打开警告,而不仅仅是在当前范围内)
  • 很公平,这是那些不容易消失的旧习惯之一... vi xxx.pl; #!/usr/bin/perl -w;它只是流动:)

标签: arrays perl hash


【解决方案1】:

胖逗号不是特殊的哈希赋值运算符。它只是一个语法糖,意思是“自动引用前一个东西”

所以:

my $hash = {
    key1 => foo(),
    key2 => 'value2'
};

意思:

my $hash = {
    'key1', foo(), 'key2', 'value2'
};

...这是一个列表,正如 willert 所说:

列表中的每个表达式都在列表上下文中进行评估。你可以通过拨打scalar foo()来解决这个问题

【讨论】:

  • 虽然确实如此,但为什么foo() 在数组上下文中被评估,而它似乎显然是列表的元素
  • @Greg:因为没有“数组上下文”之类的东西。 void、scalar 和 list (大部分)是你从纯 perl 中得到的所有东西。并且列表上下文等同于您似乎认为的“数组上下文”
  • 除非你引用数组,否则它会被评估为它的内容。所以对于'我的@a1 = (1, 2);我的@a2 = (@a1, 3, 5, 8);',第二个语句被评估为'((1, 2), 3, 5, 8)'并且@a2的长度是5,而不是4。空列表实际上会被忽略。
  • 列表中的每个表达式都在列表上下文中进行评估。不过,您可以通过调用“scalar foo()”来解决这个问题。
  • wantarray 是一个不幸的旧名称。
【解决方案2】:

匿名散列构造函数为其内部的事物提供列表上下文,因为它需要一个键和值的列表。之所以如此,是因为它就是这样。我们没有办法在代码中表示 Perl 哈希,因此您必须使用一个列表来替换键和值。 => 表示法在视觉上可以帮助我们,但不能发挥任何魔法来帮助 Perl 找出杂乱无章的东西。

当前上下文传播到子例程调用等,就像在任何其他情况下一样。

这允许您使用列表操作构建散列:

 my $hash = { 
      a => 'A',  
      map( uc, 'd' .. 'f' ),
      return_list( @args ), 
      z => 'Z' 
      };

如果您需要在标量上下文中使用某些内容,只需使用 scalar 这么说:

 my $hash = { 
      a => 'A',  
      map( uc, 'd' .. 'f' ),
      'g' => scalar return_item( @args ), 
      z => 'Z' 
      };

【讨论】:

    猜你喜欢
    • 2010-11-01
    • 2010-09-14
    • 1970-01-01
    • 2012-08-14
    • 2014-10-24
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    • 1970-01-01
    相关资源
    最近更新 更多