use v5.12; use warnings; package main; my %hash; @hash{"a".."c"} = 40 ..42; # init tie # bind wrapper %hash, 'Data::Proxy::TieHash', \%hash; # redundant, why? say $hash{a}; say @hash{"a".."c"}; delete $hash{b}; say @hash{"a".."c"}; untie %hash; # unbind wrapper say @hash{"a".."c"}; BEGIN { package Data::Proxy::TieHash; require Tie::Hash; use Scalar::Util qw/blessed/; use Carp; our @ISA = qw(Tie::ExtraHash); # All methods provided by default, define # only those needing overrides # Accessors access the storage in %{$_[0][0]}; # TIEHASH should return an array reference with the first element # being the reference to the actual storage sub _report { # uncomment to trace #carp "Doing \U$_[0]\E of $_[1] at $_[2].\n" }; sub DELETE { my ($obj, $key) = @_; my ($meta, $orig) =@$obj; _report('DELETE', $orig, $key); my $class = blessed $obj; undef $obj; untie %{$orig}; my $ret = delete $orig->{$key}; tie %{$orig}, $class, $orig; return $ret; } sub FETCH { goto &FETCH1; # use implementation } sub FETCH0 { _report('FETCH', $_[0][1], $_[1]); untie %{$_[0][1]}; my $ret = $_[0][1]->{$_[1]}; tie %{$_[0][1]}, 'Data::Proxy::TieHash', $_[0][1]; return "<$ret>" if defined $ret; return undef; } sub FETCH1 { my ($obj, $key) = @_; my ($meta, $orig) =@$obj; _report('FETCH', $orig, $key); my $class = blessed $obj; undef $obj; # avoid warning untie %{$orig}; my $ret = $orig->{$key}; tie %{$orig}, $class, $orig; return "<$ret>" if defined $ret; return undef; } }