in reply to Re: Hash value interpolation
in thread Hash value interpolation

Is it just me or is each an usability fail? I prefer traversing hashes with either keys or values.
my $ht = \%h1; for my $key ( keys %{$ht} ){ my $val = $ht->{$key}; ... }

print+qq(\L@{[ref\&@]}@{['@'x7^'!#2/"!4']});

Replies are listed 'Best First'.
Re^3: Hash value interpolation
by kyle (Abbot) on Feb 16, 2009 at 21:28 UTC

    The use of each is that it's not a memory hog. When you loop over keys, Perl has somewhere built a list of all the keys in the hash. This is especially disastrous when the hash is tied to some huge data set.

    The real problem with each is that every hash has only one iterator, and if you drop out of a loop that's walking the hash, the next loop that tries to walk that hash will start where the first left off.

      The problem can be avoided by calling keys before each.
      keys %$ht; # Reset iterator while (my ($key, $value) = each(%$ht)) {

      Update: Checked source to make sure it's efficient. Yes it is. It doesn't enumerate the keys at all in void context.


      Kyle wrote "The real problem with each is that every hash has only one iterator, and if you drop out of a loop that's walking the hash, the next loop that tries to walk that hash will start where the first left off."

      Can you give an example where the above mentioned happens or point me to an example.
      Thanks very much
        local $\ = "\n"; my %h = map { $_ => 1 } qw( a b c d ); for my $pass (1..3) { print "Pass $pass:"; while (my ($k,$v) = each %h) { print $k; last if $pass == 1; } }
        Pass 1: c Pass 2: a <---- 'c' missing b d Pass 3: c a b d
        Solution:
        local $\ = "\n"; my %h = map { $_ => 1 } qw( a b c d ); for my $pass (1..3) { print "Pass $pass:"; keys %h; # Reset iterator while (my ($k,$v) = each %h) { print $k; last if $pass == 1; } }
        Pass 1: c Pass 2: c <---- Welcome back a b d Pass 3: c a b d