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";