How each drove me crazy

I had a program like this:



my @data = qw( bla fasel foo org jawohl hmblamm glfoo sdfoo sadfasffoo) ;

my %regex = ( type1 => bla, type2 => foo);

foreach(@data) {
print $_,"\t";
print " matches " if test_it($_);
print "\n";
}

sub test_it {
my $entry = shift;
while( my($type, $regex) = each %regex) {
return 1 if $entry =~ /$regex/;
}
return 0;
}

I expected:
bla matches
fasel
foo matches
org
jawohl
hmblamm matches
glfoo matches
sdfoo matches
sadfasffoo matches

but... I got not all matches.

Long story short: each does not reset the iterator for every call. And yes in modern versions of perl this behaviour is documented -- seems like I will stick with keys

4 Comments

Why not values? You’re not using the keys for anything.

sub test_if {
my $entry = shift;
return List::Util::first { $entry =~ /$_/ } values %regex;
}

Actually this is a case where each could be fine, because the loop body is not making any calls to other code that could be messing with the hash’s iterator. He just has to reset the iterator every time he wants to start over:

sub test_it {
    my $entry = shift;
    keys %regex; # reset iterator
    while( my($type, $regex) = each %regex) {
        return 1 if $entry =~ /$regex/;
    }
    return 0;
}

Of course since he doesn’t use the keys in this example, it’s a pointless exercise to use each rather than values. (Well, if %regex is expected to grow huge then each will take much less memory than making a list of all the values, and would be faster too if a match is found quickly.)

Leave a comment

About vkroll

user-pic I blog about Perl and "modern software development", english is not my mother tongue (I am german), so I hope you get, what I mean :-)