1

我正在尝试初始化一个包含多个表达式结果的 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]));

然而,这对我来说似乎有点违反直觉。任何人都可以解释这种行为吗?

4

1 回答 1

5

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

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

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

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

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

粗箭头=>运算符不创建键值对,它只是逗号运算符的变体,将左侧的键转换为字符串。

于 2021-04-16T16:29:07.620 回答