The following snippet creates a class: Tie::Hash::PEach which allows you to set the starting point for each iterating. The starting point is set in terms of a zero-based index.

Hashes don't carry any predictable order, but unless a hash changes its keys, order does remain stable. So if you know the order and care about the point at which you begin your iterations, this snippet will allow for custom entry points.

The other primary goal of this snippet is a proof-of-concept to demonstrate (mostly to myself) how one might go about providing for a localizable 'each' iterator. The idea here is that if you localize the instance variable $obj->[1]{ITER}, you can have two separate 'each' iterator mechanisms going on, each in their own scope, without interfering with each other. This seems to be of more use than the ability to set the 'each' index. I wanted to figure out a way to allow an 'each' call in one sub's scope to act independantly of an 'each' call for the same hash in another sub's scope. This snippet accomplishes that.

I'm interested in any comments. This was intended to be a learning experience for me.

The snippet below includes a test to demonstrate the concept of localized each iterators. The class methods contain some unnecessarily explicit constructs just to make things clear. (Clearer than they appear in the Tie::Hash module.)

Update: Just wanted to credit tye for thinking of what to name the class, and Limbic~Region for getting me thinking about this topic.

package Tie::Hash::PEach; use strict; use warnings; sub FIRSTKEY { my( $self ) = shift; my( %hash ) = %{ $self->[0] }; my( $iterator ) = $self->[1]{ITER}; my( @keys ) = keys %hash; $iterator = 0 unless defined $iterator; my( @pair ) = ( $keys[ $iterator ], $hash{ $keys[ $iterator ] } ); $iterator = ( $iterator < $#keys ) ? $iterator + 1 : undef; $self->[1]{ITER} = $iterator; @{$self->[1]{KEYS}} = @keys; return wantarray ? @pair : $pair[0]; } sub NEXTKEY { my( $self ) = shift; my( %hash ) = %{ $self->[0] }; my( $iterator ) = $self->[1]{ITER}; my( @keys ) = @{ $self->[1]{KEYS} }; $iterator = 0 unless defined $iterator; my( @pair ) = ( $keys[ $iterator ], $hash{ $keys[ $iterator ] } ); if ( $iterator < $#keys ) { $iterator++; $self->[1]{ITER} = $iterator; return wantarray ? @pair : $pair[0]; } else { $iterator = undef; $self->[1]{ITER} = $iterator; return undef; } } sub TIEHASH { bless [ {}, { ITER => undef, KEYS => [] } ], shift; } sub STORE { my( $self, $key, $value ) = @_; ${$self->[0]}{$key} = $value; } sub FETCH { my( $self, $key ) = @_; return ${$self->[0]}{$key}; } sub EXISTS { my( $self, $key ) = @_; return exists ${$self->[0]}{$key}; } sub DELETE { my( $self, $key ) = @_; delete ${$self->[0]}{$key}; } sub CLEAR { my $self = shift; %{$self->[0]} = (); } sub SCALAR { my $self = shift; scalar %{$self->[0]}; } 1; package main; use strict; use warnings; use Data::Dumper; my $obj = tie my %hash, "Tie::Hash::PEach"; %hash = qw/one 1 two 2 three 3 four 4 five 5 six 6/; print "\n\nThe order of \%hash:\n"; print Dumper \%hash; { print "\n\nLocalized 'each' instance iterator for \%hash:\n"; # To change 'each' iterator for %hash, set $obj->[1]{ITER}. # Remember, the first element is 0. local $obj->[1]{ITER} = 2; my ( $key, $value ) = each %hash; print "$key => $value\n"; } print "\n\nNonlocalized 'each' instance iterator for \%hash:\n"; my ( $key, $value ) = each %hash; print "$key => $value\n";

In reply to Localizable / customizable 'each' iterator for hashes by davido

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.