Hashref赋值使用下一个键,而不是赋值undef



我正在尝试初始化一个包含多个表达式结果的hashref。我希望返回未定义结果的表达式将undef分配给相应的键。相反,赋值只是吞噬了下一个键,就好像表达式从一开始就不存在一样。

一个简单的例子可能更容易理解:

use Data::Dumper;
my $str = "vs";
my $contains = {
t => ($str =~ /t/i),
u => ($str =~ /u/i),
v => ($str =~ /v/i),
};
print(Data::Dumper->Dump([$contains]));

我希望上面的代码能打印出来:

$VAR1 = {
'v' => 1,
't' => undef,
'u' => undef
};

相反,我得到了以下内容:

$VAR1 = {
't' => 'u',
'v' => 1
};

在任务中添加一个明确的undef确实会得到我想要的结果:

use Data::Dumper;
my $str = "vs";
my $contains = {
t => ($str =~ /t/i || undef),
u => ($str =~ /u/i || undef),
v => ($str =~ /v/i || undef),
};
print(Data::Dumper->Dump([$contains]));

然而,这在我看来有点违反直觉。有人能解释这种行为吗?

您遇到了列表上下文与标量上下文的问题。为了获得所需的输出,您必须强制匹配在标量上下文中,例如,如果您真的想要undef,则必须强制匹配scalar($str =~ /t/i)($str =~ /t/i) || undef,以防匹配失败。

正则表达式匹配/.../在不同的上下文中表现不同:

  • 在标量上下文中,它根据是否匹配返回true/false值
  • 在列表上下文中,行为更为复杂:
    • 如果您有任何捕获组,则成功匹配将返回这些捕获的值
    • 如果没有捕获组,则成功匹配将返回一个包含单个元素1的列表
    • 匹配失败将返回空列表

在这里,您没有捕获组,因此如果不匹配,您的正则表达式匹配项将评估为空列表,而不是undef。所以hashref构造实际上看到了这些值:

my $contains = {
't',
'u',
'v', 1,
};

胖箭头=>运算符不会创建键值对,它只是逗号运算符的一个变体,可以将左侧的键变成字符串。

最新更新