perl 使用Dumper将数组的哈希值打印为值会导致无限递归

siv3szwd  于 2023-01-17  发布在  Perl
关注(0)|答案(1)|浏览(155)

下面的代码会导致无限递归。如果打印时没有使用Dumper,那么它会按预期工作。为什么Dumper会导致递归?

use Data::Dumper;

my %hash1 = (
          'key1' => ['val1']
);

while (my ($key, $value) = each %hash1) {
    print Dumper \%hash1;
}
rkttyhzu

rkttyhzu1#

each,你在循环中使用它,Data::Dumper用它来迭代哈希值的内容。
the documentation of each(着重号已添加):
each使用的迭代器附加到散列或数组,并在应用于同一散列或数组的所有迭代操作之间共享。因此,在单个散列或数组上使用each的所有迭代器都前进到相同的迭代器位置。在同一散列或数组上使用keysvalues时,使用each的所有迭代器也会重置迭代器。或者由列表上下文中引用的散列(而不是数组)定义。这使得基于each的循环非常脆弱:很容易在迭代器已经部分通过对象的情况下实现这样的循环,或者在循环体执行期间意外地破坏迭代器状态。在开始循环之前显式地重置迭代器也很容易,但是没有办法将循环使用的迭代器状态与可能在循环体中执行的任何其他操作使用的迭代器状态隔离开来。要避免这些问题,请使用foreach循环,而不要使用while-each
就像这样:

#!/usr/bin/env perl
use warnings;
use strict;
use Data::Dumper;

my %hash1 = (
          'key1' => ['val1']
);

foreach my $key (keys %hash1) {
    print Dumper \%hash1;
}

基本上,不要使用each,除非您可以完全控制循环体中的散列对结果的处理。
下面的文档解释了无限循环的确切原因:
each已经返回来自散列或数组的所有条目之后,对each的下一次调用在列表上下文中返回空列表并且在标量上下文中返回undef;在那个调用之后的下一个调用重新开始迭代。
Dumper()代码中的each循环首先重置内部迭代器,然后重复直到返回空列表;然后在while循环的测试中再次调用each,并从散列的第一个(唯一的)元素重新开始,然后永远重复。

相关问题