为什么组合 Perl 哈希值和每个表达式不起作用?

Wal*_*ard 5 iteration perl hash concatenation

我最近遇到了这个并且感到非常不满:

while (my ($key, $value) = each (%hash1, %hash2)) {
} 
Run Code Online (Sandbox Code Playgroud)

出现此错误:现在禁止在标量上进行实验每个......

但这似乎是使用多余变量的相同操作:

my %h = (%hash1, %hash2);
while (my ($key, $value) = each %h) {
} 
Run Code Online (Sandbox Code Playgroud)

编译并运行得很好。

这是什么原因,我的不满是否有道理?

Sil*_*olo 6

这里出现了几个问题。首先,让我们解决当前的问题。

my %h = (%hash1, %hash2);
while (my ($key, $value) = each(%hash1, %hash2)) { ... }
Run Code Online (Sandbox Code Playgroud)

each其实就是Perl中的一个普通函数,并不是什么特殊的语法什么的。因此,就 Perl 而言,您调用的是each两个参数,而不是一个。需要一个数组或哈希值(基本上是以oreach开头的值),这就是有效的原因。您可以创建一个本地哈希并使用更复杂的语法传递它%@each(%h)

while (my ($key, $value) = each(%{{%hash1, %hash2}})) { ... }
Run Code Online (Sandbox Code Playgroud)

在这里,我们使用 hashref 构造函数来创建一个新的 hash {%hash1, %hash2}。这是一个恰好指向散列的标量值。然后我们立即用 取消引用它%{...}。不幸的是,这会导致另一个问题。如果您尝试运行此代码,它将正常编译,但随后会无限循环。为了弄清楚这是为什么,我们需要做一个简短的切线。

each在 Perl 中有点奇怪。它实际上是有状态的,并将所谓的调用状态存储在哈希对象中。所以

my %h = (a => 1, b => 2);
say each(%h);
say each(%h);
Run Code Online (Sandbox Code Playgroud)

这两个调用each将返回不同的值。一个返回("a", 1),另一个返回("b", 2)(两次返回的顺序未指定)。

现在,您的while条件将在每次循环时重新运行,因此如果我们在每次循环迭代时创建一个临时哈希,并且 Perleach每次都尝试将其状态存储在哈希中,那么您将永远不会到达迭代的末尾因为在任何给定的哈希被删除并替换为新哈希之前,您永远不会对它进行多次迭代。

我的建议是只使用临时的。即使您可以使用合并哈希来完成此操作each,您也会在每次循环迭代时创建一个新的合并哈希。或者,您可以keys简单地将所有键作为单个列表获取。这只会发生一次,因为它是作为for循环的头部发生的。

for my $key (keys %{{%hash1, %hash2}}) {
    my $value = $hash1{$key} // $hash2{$key};
    ...
}
Run Code Online (Sandbox Code Playgroud)