I almost feel like saying “it’s me again!”.
Anyway, here we go.
I like using while $object->next() style constructs. They appeal to me and seem “neat”.
Now, when the thing I’m iterating over is an array, it’s straightforward (“shift @ary or return undef“)
sub next {
my ( $self, $args ) = @_;
my $next = shift @{ $self->{list_of_things} } or return undef;
my ( $car, $engine_size, $color )
= split( /\Q$opts->{fieldsep}/, $next );
$self->car = $host;
$self->engine_size = $engine_size;
$self->color = $color;
}
In this example I use AUTOLOAD to create the getters and setters and then have those instance variables available in my object during the while loop.
I’d like to do something similar but with the “list_of_things” being a %hash.
Here’s a non-OO example that doesn’t make it into the first iteration. Any ideas why?
(The total “list_of_things” is not that big – maybe 100 entries – so to do a keys(%{$hash}) every time doesn’t seem too wasteful to me).
use strict;
use warnings;
use Data::Dumper;
my $list_of_things = {
volvo => {
color => "red",
engine_size => 2000,
},
bmw => {
color => "black",
engine_size => 2500,
},
mini => {
color => "british racing green",
engine_size => 1200,
}
};
sub next {
my $args = $_;
my @list = keys( %{$list_of_things} );
return undef if scalar @list == "0";
my $next = $list_of_things->{ $list[0] };
delete $list_of_things->{ $list[0] };
return $next;
}
while ( next()) {
print Dumper $_;
print scalar keys %{ $list_of_things }
}
Is there a better way of doing this? Am I doing something crazy?
EDIT:
I tried Ikegami’s suggestion. Of course, Ikegami’s example works flawlessly. When I try and abstract a little, so that all that is exposed to the object is a next->() method, I get the same “perl-going-to-100%-cpu” problem as in my original example.
Here’s a non-OO example:
use Data::Dumper qw( Dumper );
sub make_list_iter {
my @list = @_;
return sub { @list ? shift(@list) : () };
}
sub next {
make_list_iter( keys %$hash );
}
my $hash = { ... };
while ( my ($k) = next->() ) {
print Dumper $hash->{$k};
}
It does not seem to get past the first step of the while() loop.
I am obviously missing something here…
If you don’t want to rely on the hash’s builtin iterator (used by each, keys and values), there’s nothing stopping you from making your own.