Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I have a hash tying package that works EXCEPT when references are returned (references as values -- not keys) and used in block dereferencing constructs like this:

my $h = {}; tie %$h, "MyTie"; $h->{KEY} = []; push(@{$h->{KEY}}, (qw/foo bar/)); # THIS FAILS
The failure is: Can't use an undefined value as an ARRAY reference. Replacing the fetch line with one that does an assignment does work:
push(@{my $x = $h->{KEY}}, (qw/foo bar/)); # THIS WORKS!

If I put a print statement in the Tie package's FETCH method the value is there, as expected, before it returns in all cases. That, along with it working if assigned locally first, leads me to believe this is a Perl bug. But I've found no references to any problems like this anywhere.

I've built about a half dozen similar hash ties without this problem. This tie, like some of the others, is a hash but it doesn't use itself as the data holder directly -- it refers to another anonymous hash that implements the hash being tied, kind of like this in TIEHASH:

sub TIEHASH { my $class = shift; my $self = bless({HASH_DATA => {}}, $class); return $self; }
All the methods then use $self->{HASH_DATA} to get at the real data values being tied. The rest of the $self hash is used for housekeeping.

This Tie relies on lots of internal code so I can't post it. I also can't reproduce the problem with a smaller tie. The tie is just using other hashes behind the scenes for data normalization and validation -- no databases, files, shared memory or anything else unusual. The hash being tied is also a blessed (object) reference.

Everything else works. Nothing unusual from the debugger or using -w. It fails the same across all versions of Perl 5.5 and 5.6 I tried. I've looked at the Perl source and don't see anything there so far. I'm running on Solaris. I have not tried anywhere else yet (next on my list).

Replies are listed 'Best First'.
Re: error dereferencing array in a tied hash
by Henri Icarus (Beadle) on Sep 29, 2001 at 20:19 UTC
    Yep, I've seen that too. The issues is, I think, that what you get from the tied hash is a reference to the method in the tied object, and that doesn't get executed in context of the array dereference, but it does in the context of assigning the value to a variable. Why this would be, I don't know.

    -I went outside... and then I came back in!!!!

      Know of any workarounds that don't involve changing all the outside hash access code? The idea of the tie is to leave that code alone while adding something hidden. I've tried lots of things with no luck. Strange that it only happens with some ties, and when it does, it does it consistently with that tie. That leads me to believe there's something I can do in the tie code to make it work. What, I don't know ...

Re: error dereferencing array in a tied hash
by converter (Priest) on Sep 29, 2001 at 21:31 UTC

    Show us your STORE and FETCH subs. Maybe there's a problem there that you've missed.

      They won't make much sense on their own since they call out to other code, but here they are anyway. As I noted, I've put print statements in and FETCH has the correct value right at return time. That value is only returned if I assign it, as also noted -- not as a dereference on the hash element FETCH is operating on behalf of.

      sub FETCH { my $self = shift; my $key = shift; my $value = $self->{USER_OPT}->direct_get($key, $self->{ATTRS}); return $value; } sub STORE { my $self = shift; my $key = shift; my $value = shift; my $name; ($name, $value) = $self->{USER_OPT}->direct_set($key, $value, $self->{ATTRS}); return $value; }