package RJT::LocalHash { use parent 'Tie::Hash'; use List::MoreUtils qw/uniq/; use Carp; sub TIEHASH { my ($class, $orig) = @_; croak 'Expected HASH ref, not `'.ref($orig)."'" unless 'HASH' eq ref $orig; bless { orig => $orig, del => { }, new => { } }, $class; } sub STORE { delete $_[0]{del}{$_[1]}; $_[0]{new}{$_[1]} = $_[2] } sub EXISTS { not exists $_[0]{del}{$_[1]} and (exists $_[0]{new}{$_[1]} or exists $_[0]{orig}{$_[1]}) } sub FETCH { return if exists $_[0]{del}{$_[1]}; exists $_[0]{new}{$_[1]} ? $_[0]{new}{$_[1]} : $_[0]{orig}{$_[1]} } sub FIRSTKEY { # Initialize the iterator as union of both hash key sets # minus anything that's been locally deleted my @each = grep { not exists $_[0]{del}{$_} } uniq keys $_[0]{orig}, keys $_[0]{new}; $_[0]{each} = \@each; shift @each; } sub NEXTKEY { shift $_[0]{each} } sub DELETE { $_[0]{del}{$_[1]} = 1; $_[0]{new}{$_[1]} // $_[0]{orig}{$_[1]}; } }