# from Extending and Embedding Perl, section 4.5
$HE = {
NEXT => $HE_next,
HEK => {
HASH => $hash,
LEN => length($key),
KEY => $key,
}
VAL => $SV,
};
####
$elem->delete;
$elem->exists;
$$elem = $x;
print $elem; # overloaded for convenience
print $$elem;
####
use strict;
use warnings;
package Tie::LazyHash;
require Tie::Hash;
our @ISA = 'Tie::StdHash';
sub FETCH {
Tie::LazyHash::Elem->new( @_ );
}
package Tie::LazyHash::Elem;
use Class::InsideOut qw(id private register);
use Scalar::Util 'weaken';
use overload 'bool' => '_get';
use overload '""' => '_get';
use overload '0+' => '_get';
private _hash => my %hash;
private _key => my %key;
sub _hash;
sub _key;
sub new {
my ($proto, $hash, $key) = @_;
my $class = ref $proto || $proto;
my $self = bless \do{ my $bidding }, $class;
tie $$self, 'Tie::LazyHash::Elem::Inner', id($self);
weaken( $hash{id $self} = $hash );
$key{id $self} = $key;
register $self;
}
sub _get {
my $self = shift;
my $hash = _hash $self;
return $hash->{_key $self};
}
sub _set {
my ($self, $val) = @_;
my $hash = _hash $self;
$hash->{_key $self} = $val;
}
sub delete {
my $self = shift;
my $hash = _hash $self;
delete $hash->{_key $self};
}
sub exists {
my $self = shift;
my $hash = _hash $self;
exists $hash->{_key $self};
}
sub _hash {
my $self = shift;
if (ref $self) {
$self = id $self;
}
return $hash{$self};
}
sub _key {
my $self = shift;
if (ref $self) {
$self = id $self;
}
return $key{$self};
}
package Tie::LazyHash::Elem::Inner;
sub TIESCALAR {
my ($class, $id) = @_;
bless \$id, $class;
}
sub FETCH {
my $self = shift;
Tie::LazyHash::Elem::_get($$self);
}
sub STORE {
my ($self, $val) = @_;
Tie::LazyHash::Elem::_set($$self, $val);
}
1;
__END__