Hash::...erator(3pm)

🌸 Hash::StoredIterator β€” a.k.a. Hash::...erator(3pm) πŸ’…

okay bestie, sit down, hydrate, because we're about to talk about the ✨internal iterator✨ that lives inside every single Perl hash and is lowkey the reason your nested loops are a mess. This is the manual page for Hash::StoredIterator, and she is iconic.


πŸ¦‹ NAME

Hash::StoredIterator β€” functions for accessing a hashes internal iterator. no cap, that's the whole job. 🫢


✨ DESCRIPTION

okay so. In perl all hashes have an internal iterator. Every single one. And this iterator is the thing that each() uses, and also keys() and values(). The way they all share the same iterator is exactly why they interact so badly with each other when you nest them. it's giving toxic polycule. 😭

Hash::StoredIterator gives you access to get, set, and init the iterator inside a hash. Which means you can store the current iterator, go do your each/keys/values/etc business, and then restore the iterator. That's how you make sure you're not ruining things for literally every other user of the iterator. mutual respect, periodt. πŸ’–

Along with the low-level get/set/init functions, there are also 2 variations of each() which let you act upon each key/value pair in a safer way than vanilla each(). vanilla is fine but we're not doing vanilla here. πŸ“

This module can also export new implementations of keys() and values() which stash and restore the iterator so that they are safe to use within each(). slay.


πŸŽ€ SYNOPSIS

use Hash::StoredIterator qw{
    hmap
    hkeys
    hvalues
    iterator
    hash_get_iterator
    hash_set_iterator
    hash_init_iterator
};

my %hash = map { $_ => uc( $_ )} 'a' .. 'z';

my @keys = hkeys %hash;
my @values = hvalues %hash;

Each section below is functionally identical. fr fr, same energy, different outfit. πŸ‘‘

my $iterator = iterator %hash;
while( my ( $k, $v ) = $i->() ) {
    print "$k: $value\n";
}

hmap { print "$a: $b\n" } %hash;

hamp { print "$_: $b\n" } %hash;

hmap {
    my ( $key, $val ) = @_;
    print "$key: $val\n";
} %hash;

It is safe to nest calls to hmap(), iterator(), hkeys(), and hvalues(). nest away, bestie, go feral. πŸͺ†

hmap {
    my ( $key, $val ) = @_;
    print "$key: $val\n";
    my @keys = hkeys( %hash );
} %hash;

hmap() and iterator() will also properly handle calls to "CORE::each", "CORE::keys", and "Core::values" nested within them. yes the capitalisation there is exactly how the original says it, don't come for me. πŸ™ˆ

hmap {
    my ( $key, $val ) = @_;
    print "$key: $val\n";

    # No infinite loop!
    my @keys = keys %hash;
} %hash;

Low Level: the no-frills aisle. 🌈

hash_init_iterator( \%hash );
my $iter = hash_get_iterator( \%hash );
# NOTE: Never manually specify an $iter value, ALWAYS use a value from
# hash_get_iterator.
hash_set_iterator( \%hash, $iter );

πŸ’– EXPORTS

  • my $i = iterator %hash β€” Get an iterator that can be used to retrieve key/value pairs. πŸ¦‹
my $i = iterator %hash;
while( my ($k, $v) = $i->() ) {
    ...
}

The iterator is a coderef, so you call it like this: "$i-"()>. You can also use the sub anywhere you would use any other coderef. she's versatile like that. πŸ’…

  • hmap( \&callback, %hash ) / hmap { ... } %hash β€” Iterate each key/pair calling "$callback-"( $key, $value )> for each set. In addition $a and $_ are set to the key, and $b is set to the value. This is done primarily for convenience of matching against the key, and short callbacks that will be cluttered by parsing @_ noise.

Note: See caveats. ⚠️ (yes, those caveats. we'll get there.)

  • my @keys = hkeys( %hash ) β€” Same as the builtin keys(), except it stores and restores the iterator. ✨

Note: Overriding the builtin keys(), even locally, causes strange interactions with other builtins. When trying to export hkeys as keys, a call to "sort keys %hash" would cause undef to be passed into keys() as the first and only argument. 😭 yeah. that.

  • my @values = hvalues( %hash ) β€” Same as the builtin values(), except it stores and restores the iterator. 🌸

Note: Overriding the builtin values(), even locally, causes strange interactions with other builtins. When trying to export hvalues as values, a call to "sort values %hash" would cause undef to be passed into values() as the first and only argument. same curse, different function. πŸ’€

  • my $i = hash_get_iterator( \%hash ) β€” Get the current iterator value. 🫢
  • hash_set_iterator( \%hash, $i ) β€” Set the iterator value.
Note: Only ever set this to the value retrieved by hash_get_iterator(), setting the iterator in any other way is untested, and may result in undefined behavior. do NOT freestyle this one, bestie. I am begging. πŸ™
  • hash_init_iterator( \%hash ) β€” Initialize or reset the hash iterator. clean slate, fresh start, main character reboot. 🧚

🌈 DEPRECATED

These have been deprecated because they were terrible names. eich was also deprecated because it was unnatural to use. honestly? fair. the vibes were off. 🚫

  • eich β€” use iterator() instead
  • eech β€” use hmap instead

⚠️ CAVEATS

Modification of hash during iteration

Just like with the builtin each(), modifying the hash between calls to each is not recommended and can result in undefined behavior. The builtin each() does allow for deleting the iterations key, however that is NOT supported by this library. so like. don't. 😀

sort() edge case

For some reason "[sort hkeys %hash]" and "[sort hkeys(%hash)]" both result in a list that has all the keys and values (and strangely not in sorted order). However "[sort(hkeys(%hash))]" works fine. the parentheses are doing the lord's work here. πŸ™Œ


πŸ‘‘ AUTHORS

Chad Granum <exodist7@gmail.com>


Copyright (C) 2013 Chad Granum

Hash-StoredIterator is free software; Standard perl licence.

Hash-StoredIterator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.


and that's the whole page, bestie πŸ’œ this was perl v5.42.3, dated 2026-08-20, and the manual is Hash::...erator(3pm). go forth and nest your iterators responsibly. mwah. 🫢✨

πŸ“¦ where this page comes from