I started using the Tie::Memozie routine yesterday and found that I could not get my custom EXISTS function to work. I think I may have found a couple of bugs, and I wanted to run it past the monks before opening a bug report. I have already notified the Module Author, but since Tie::Memoize is now included in the Core distribution I am planning to open a bug against perl5 core.

**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.

sub deep_exists { my ($key, $data) = @_; warn " Cache miss on exist key ($key) for ". $data->{container}{type} ." object\n"; return undef; }
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).

So I decided to dig a bit deeper. Here is the code from the Tie::Memoize::EXISTS handler:

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 }
from the Tie::Memoize perldoc :
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

my @res = $a->[3]($key,$a->[4]); $_[0][1]{$key} = 0, return unless @res;
So when I returned undef, it created an array with 1 element, which then satisfies the unless @res predicate.

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?


In reply to Potential Tie::Memoize Bug by satchm0h

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.