Skip to content

evalEmpire/Hash-StoredIterator

Repository files navigation

NAME

    Hash::StoredIterator - Functions for accessing a hashes internal
    iterator.

DESCRIPTION

    In perl all hashes have an internal iterator. This iterator is used by
    the each() function, as well as by keys() and values(). Because these
    all share use of the same iterator, they tend to interact badly with
    each other when nested.

    Hash::StoredIterator gives you access to get, set, and init the
    iterator inside a hash. This allows you to store the current iterator,
    use each/keys/values/etc, and then restore the iterator, this helps you
    to ensure you do not interact badly with other users of the iterator.

    Along with 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()

    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().

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.

        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()

        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.

        hmap {
            my ( $key, $val ) = @_;
            print "$key: $val\n";
    
            # No infinite loop!
            my @keys = keys %hash;
        } %hash;

    Low Level:

        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.

    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.

    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.

    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.

    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.

    hash_init_iterator( \%hash )

      Initialize or reset the hash iterator.

DEPRECATED

    These have been deprecated because they were terrible names. eich was
    also deprecated because it was unnatural to use.

    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.

    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.

AUTHORS

    Chad Granum [email protected]

COPYRIGHT

    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.

About

Access to iterator inside perl hashes, plus helper functions.

Resources

License

Stars

Watchers

Forks

Packages

No packages published