sub make_hash_iterator { my ($hash) = @_; my @keys = keys %hash; return sub { return () if !@keys; if (wantarray) { my $key = shift(@keys); return ($key, $hash->{$key}); } else { $_[0] = shift(@keys); return 1; } }; } my $i = make_hash_iterator(\%hash); while ($i->(my $key)) { # scalar context ... } my $i = make_hash_iterator(\%hash); while (my ($key) = $i->()) { # list context ... # Will fail for '' and '0' } # without parens around $key. my $i = make_hash_iterator(\%hash); while (my ($key, $val) = $i->()) { ... }