This is probably best done with a tied hash. Tied variables allow you to define the implementation of the low level operations of the variable. In this case, we want a special fetch method that dies when accessing non-existant keys:
use warnings;
use strict;
{package Safe::Hash;
require Tie::Hash;
our @ISA = 'Tie::StdHash';
use Carp;
sub FETCH {
exists $_[0]{$_[1]} or croak "no key $_[1]";
$_[0]{$_[1]}
}
}
tie my %safe => 'Safe::Hash';
$safe{a} = 5; # ok
print $safe{a}, "\n"; # ok
$safe{b} = 10; # ok
print $safe{bb}, "\n"; # dies
In the implementation of Safe::Hash
above, I first load Tie::Hash
which provides Tie::StdHash
. Setting @ISA
to Tie::StdHash
provides our new package with tie methods that behave the same way as normal hashes. Each of the tie methods are outlined on http://perldoc.perl.org/perltie.html
In this case the only method to override is FETCH
which is passed a reference to the hidden tied object (a hashref in this case), and the key to use. It checks if the slot exists, and either returns it or throws an error