为什么Perl在声明时将哈希元素视为列表上下文?

时间:2010-02-25 09:07:08

标签: arrays perl hash

鉴于此代码:

#!/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')的调用,它返回一个空数组,破坏(旋转?)哈希结构。

2 个答案:

答案 0 :(得分:7)

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

所以:

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

意思是:

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

......这是一份清单,正如威勒特所说:

  

列表中的每个表达式都在列表上下文中计算。您可以致电scalar foo()

来解决这个问题

答案 1 :(得分:3)

匿名哈希构造函数为其中的内容提供列表上下文,因为它需要键和值列表。就是这样,因为它就是这样。我们没有办法在代码中表示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' 
      };