Greetings- At long last, I found some time to work on your suggested improvement. It's a
great idea but sadly Perl's implementation of lvalue subs is not up to the task. In fairness,
perlsub states clearly, "Lvalue subroutines are still experimental...".
The main issue is that when using a tied hash the STORE method is not called on assignment,
so any special semantics are completely lost. This is a showstopper since a key motivation for
Hash::AutoHash is to make it easy to define subclasses that use tied hashes to implement
special semantics. An example is Hash::AutoHash::MultiValued.
A second problem is that Perl's implementation of lvalue subs is fragile. The sub has to return
the actual hash entry and cannot return something that Perl puts in a temporary. It seems the
last line of the sub has to be like "$hash->{$key}" and cannot even be "return $hash->{$key}".
The attached file illustrates both a working lvalue sub and the problem with tied hashes.
Please let me know if I'm doing something wrong or you see a way to work around the tied hash
problem.
Thanks,
Nat
On Mon Oct 03 16:05:47 2011, TOBYINK wrote:
Show quoted text> Nuff said.
# play with lvalue subs
package Hash;
use Tie::Hash;
use base qw(Tie::StdHash);
sub TIEHASH {
my $storage = bless {}, shift;
print "New ReportHash created, stored in $storage.\n";
$storage
}
sub FETCH : lvalue {
print "Fetching data with key $_[1] at $_[0].\n";
$_[0]{$_[1]};
# $value="fetched $_[0]{$_[1]}";
# $value;
}
sub STORE {
print "Storing data with key $_[1] at $_[0].\n";
$_[0]{$_[1]} = "$_[1]=>$_[2]"
}
sub fetch : lvalue {
my($self,$key)=@_;
FETCH($self,$key)
}
package main;
my $hash={}; # doesn't work if $hash not initialized
sub foo : lvalue {
my($self,$key)=splice(@_,0,2);
if (@_) {$self->{$key}=$_[0]};
$self->{$key};
}
print foo($hash,'xxx')=123,"\n";
print '$hash->{xxx}=',$hash->{xxx},", should be 123\n";
$ttt=tie %ttt,'Hash';
$ttt{xxx}=123;
print '$ttt{xxx}=',$ttt{xxx},", should be 'xxx=>123'\n";
print '$ttt->fetch(xxx)=',$ttt->fetch('xxx'),", should be 'xxx=>123'\n";
$ttt->fetch('xxx')=456;
print '$ttt{xxx}=',$ttt{xxx},", should be 'xxx=>456' not simply 456\n";
print "break here\n";