下面的代码会导致无限递归。如果打印时没有使用Dumper,那么它会按预期工作。为什么Dumper会导致递归?
use Data::Dumper; my %hash1 = ( 'key1' => ['val1'] ); while (my ($key, $value) = each %hash1) { print Dumper \%hash1; }
rkttyhzu1#
each,你在循环中使用它,Data::Dumper用它来迭代哈希值的内容。从the documentation of each(着重号已添加):each使用的迭代器附加到散列或数组,并在应用于同一散列或数组的所有迭代操作之间共享。因此,在单个散列或数组上使用each的所有迭代器都前进到相同的迭代器位置。在同一散列或数组上使用keys或values时,使用each的所有迭代器也会重置迭代器。或者由列表上下文中引用的散列(而不是数组)定义。这使得基于each的循环非常脆弱:很容易在迭代器已经部分通过对象的情况下实现这样的循环,或者在循环体执行期间意外地破坏迭代器状态。在开始循环之前显式地重置迭代器也很容易,但是没有办法将循环使用的迭代器状态与可能在循环体中执行的任何其他操作使用的迭代器状态隔离开来。要避免这些问题,请使用foreach循环,而不要使用while-each。就像这样:
each
Data::Dumper
keys
values
foreach
while
#!/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,并从散列的第一个(唯一的)元素重新开始,然后永远重复。
undef
Dumper()
1条答案
按热度按时间rkttyhzu1#
each
,你在循环中使用它,Data::Dumper
用它来迭代哈希值的内容。从the documentation of
each
(着重号已添加):each
使用的迭代器附加到散列或数组,并在应用于同一散列或数组的所有迭代操作之间共享。因此,在单个散列或数组上使用each
的所有迭代器都前进到相同的迭代器位置。在同一散列或数组上使用keys
或values
时,使用each
的所有迭代器也会重置迭代器。或者由列表上下文中引用的散列(而不是数组)定义。这使得基于each
的循环非常脆弱:很容易在迭代器已经部分通过对象的情况下实现这样的循环,或者在循环体执行期间意外地破坏迭代器状态。在开始循环之前显式地重置迭代器也很容易,但是没有办法将循环使用的迭代器状态与可能在循环体中执行的任何其他操作使用的迭代器状态隔离开来。要避免这些问题,请使用foreach
循环,而不要使用while
-each
。就像这样:
基本上,不要使用
each
,除非您可以完全控制循环体中的散列对结果的处理。下面的文档解释了无限循环的确切原因:
在
each
已经返回来自散列或数组的所有条目之后,对each
的下一次调用在列表上下文中返回空列表并且在标量上下文中返回undef
;在那个调用之后的下一个调用重新开始迭代。Dumper()
代码中的each
循环首先重置内部迭代器,然后重复直到返回空列表;然后在while
循环的测试中再次调用each
,并从散列的第一个(唯一的)元素重新开始,然后永远重复。