简体   繁体   中英

Printing hash of array as values with Dumper leads to infinite recursion

The following code leads to infinite recursion. If printed without Dumper then it works as expected. Why Dumper causes recursion?

use Data::Dumper;

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

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

each to blame here. You're using it in your loop, and Data::Dumper uses it to iterate over the contents of hashes.

From the documentation of each (Emphasis added):

The iterator used by each is attached to the hash or array, and is shared between all iteration operations applied to the same hash or array. Thus all uses of each on a single hash or array advance the same iterator location. All uses of each are also subject to having the iterator reset by any use of keys or values on the same hash or array, or by the hash (but not array) being referenced in list context. This makes each -based loops quite fragile: it is easy to arrive at such a loop with the iterator already part way through the object, or to accidentally clobber the iterator state during execution of the loop body. It's easy enough to explicitly reset the iterator before starting a loop, but there is no way to insulate the iterator state used by a loop from the iterator state used by anything else that might execute during the loop body. To avoid these problems, use a foreach loop rather than while - each .

Like so:

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

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

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

Basically, don't use each unless you have full control over what's done with the hash in the body of the loop over its results.

The exact cause of an infinite loop is explained with this bit of documentation:

After each has returned all entries from the hash or array, the next call to each returns the empty list in list context and undef in scalar context; the next call following that one restarts iteration.

The each loop in the Dumper() code first resets the internal iterator, and then repeats until it returns an empty list; then each is called again in the test of your while loop and starts afresh with the first (only) element of the hash, and repeats forever.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM