satchm0h has asked for the wisdom of the Perl Monks concerning the following question:
**update - the maintainer email address is bouncing, so no insights coming from that direction.
I passed a reference to this subroutine as my custom EXISTS handler with the assumption that it would always fail an exists check. My understanding was that this routine would only get called on exists test when there was a cache miss.
Sure enough, it only runs when an exists test is done on an element that misses. To my surprise, when I tested existence of a non-existent hash element, I saw my warning and the exists check passed (as opposed to the expected failure).sub deep_exists { my ($key, $data) = @_; warn " Cache miss on exist key ($key) for ". $data->{container}{type} ." object\n"; return undef; }
So I decided to dig a bit deeper. Here is the code from the Tie::Memoize::EXISTS handler:
from the Tie::Memoize perldoc :sub EXISTS { my ($a,$key) = (shift, shift); # STEP 1 return 1 if exists $a->[0]{$key}; # Have data # STEP 2 my $cache = $a->[1]{$key}; return $cache if defined $cache; # Existence cache # STEP 3 my @res = $a->[3]($key,$a->[4]); $_[0][1]{$key} = 0, return unless @res; # Cache non-existence # STEP 4 # Now we know it exists return ($_[0][1]{$key} = 1) if $a->[5]; # Only existence reported # STEP 5 # Now know the value $_[0][0]{$key} = $res[0]; # Store data return 1 }
The structure of the tied() data is an array reference with elements 0: cache of known values 1: cache of known existence of keys 2: FETCH function 3: EXISTS function 4: $data
There are two problems here that I see. They both crop up in STEP 3. First, the one that caused my specific problem is that the return value of the provided custom exist function is assigned to an array
So when I returned undef, it created an array with 1 element, which then satisfies the unless @res predicate.my @res = $a->[3]($key,$a->[4]); $_[0][1]{$key} = 0, return unless @res;
According to the perltie documentation this is not the correct behavior for tied hash exists functions. I am able to work around this by returning the empty list instead.
The second potential issue is with the $_[0][1]{$key} = 0 assignment. It looks like the intent is to cache the fact that we already know this does not exist. That way subsequent exist tests will fail in STEP 2 without needed to call the test function again. However, since the data structure is shifted into the $a variable the correct way to accomplish this goal is $a->[1]{$key} = 0. That being said, I am assuming I understand the intent of this assignment. I may very well not understand what is being done here.
What do you think?
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Potential Tie::Memoize Bug
by chromatic (Archbishop) on Mar 16, 2005 at 19:35 UTC | |
by satchm0h (Beadle) on Mar 17, 2005 at 01:22 UTC | |
|
Re: Potential Tie::Memoize Bug
by nobull (Friar) on Mar 16, 2005 at 18:14 UTC |