I have added another layer of bookkeeping to make it simpler to use assuming that something like HASH(0x7c2300) is a unique identifier for a hash and does not change during runtime.
use strict;
use warnings;
sub hashIteratorFactory {
my $h = shift;
my @both;
my $exhausted = 0;
return sub {
my $i = 0;
return sub {
my ($k, $v);
if( !defined $both[$i] ) {
if( !$exhausted and (( $k, $v ) = each %$h) ) {
push @both, [ $k, $v ];
} else {
$exhausted = 1;
$i = 0;
return wantarray() ? () : undef();
}
} else {
( $k, $v ) = @{$both[$i]};
}
$i++;
return wantarray() ? ( $k, $v ) : $k;
}
}
}
my %hashIteratorStore;
sub hashIterator {
my $h = shift;
die "Not a hash reference!" unless ref $h eq 'HASH';
$hashIteratorStore{$h} //= hashIteratorFactory($h);
return $hashIteratorStore{$h}->();
}
my %h;
@h{'a'..'d'} = 1..4;
print \%h,"\n";
my %h2;
@h2{'e'..'i'} = 5..8;
my $i1 = hashIterator( \%h );
my $i2 = hashIterator( \%h );
print "1:",$i1->(),"\n";
print "1:",$i1->(),"\n";
print "2:",$i2->(),"\n";
print "1:",$i1->(),"\n";
print "1:",$i1->(),"\n";
my $i4 = hashIterator( \%h2 );
print "2:",$i2->(),"\n";
print "2:",$i2->(),"\n";
print "1:",$i1->(),"\n";
print "4:",$i4->(),"\n";
print "4:",$i4->(),"\n";
print "1:",$i1->(),"\n";
print "2:",$i2->(),"\n";
print "2:",$i2->(),"\n";
my $i3 = hashIterator( \%h );
while( my ($k, $v) = $i3->() ) {
print "3:$k$v\n";
}
print "2:",$i2->(),"\n";
print "1:",$i1->(),"\n";
This is really only a starting point as it is really read-only. If the hash is changed somewhere inbetween, the cached keys and values will be unmodified. So more work is required.
|