in reply to Re: Memoize::Expire oddity
in thread Memoize::Expire oddity

I tried MERGE too and got the same error. I was using 5.16.2 on Windows. That's my work box. I'm home now on Linux, MERGE is also not helping me. am I using the option wrongly?

r@Che ~ $ perl -MMemoize -MMemoize::Expire -E "sub f {int rand 100}; \ tie my %cache => 'Memoize::Expire',LIFETIME=>2,LIST_CACHE=>' +MERGE';\ memoize 'f',SCALAR_CACHE => [HASH => \%cache ];\ for (1..10) {say f(); sleep 1}" 45 45 45 45 45 45 45 45 45 45 r@Che ~ $ perl -v This is perl 5, version 14, subversion 2 (v5.14.2) built for x86_64-li +nux-gnu-thread-multi (with 65 registered patches, see perl -V for more detail) Copyright 1987-2011, Larry Wall Perl may be copied only under the terms of either the Artistic License + or the GNU General Public License, which may be found in the Perl 5 source ki +t. Complete documentation for Perl, including FAQ lists, should be found +on this system using "man perl" or "perldoc perl". If you have access to + the Internet, point your browser at http://www.perl.org/, the Perl Home Pa +ge.

Cheers,
R.

Pereant, qui ante nos nostra dixerunt!

Replies are listed 'Best First'.
Re^3: Memoize::Expire oddity
by ryanc (Monk) on Aug 16, 2013 at 18:32 UTC
    $ perl -MMemoize -MMemoize::Expire -E " \ sub f { int rand 100 }; \ tie my %cache => 'Memoize::Expire', LIFETIME => 2; \ memoize 'f', LIST_CACHE => 'MERGE', \ SCALAR_CACHE => [ HASH => \%cache ]; \ for (1..10) { say f(); sleep 1 }" 62 62 56 56 39 39 85 85 42
      Thanks for this example. With a little further modification it demonstrates that Memoize::Expire won't work for functions returning lists:
      perl -MMemoize -MMemoize::Expire -E " \ sub f { ('X',int rand 100) }; \ tie my %cache => 'Memoize::Expire', NUM_USES => 3; \ memoize 'f', LIST_CACHE => 'MERGE', \ SCALAR_CACHE => [ HASH => \%cache ]; \ for (1..6) { say f() }"
      X63
      X
      X
      X67
      X
      X
      
      You should be able to use any tied hash- not only Memoize::Expire but also any of the file-stores- if you first wrap it in something that will freeze/thaw the list beforehand. Example:
      perl -MMemoize -MMemoize::Expire -MSerializeValues -E " \ sub f { ('X',int rand 100) }; \ tie my %subcache => 'Memoize::Expire', NUM_USES => 3; \ tie my %cache => 'SerializeValues', \%subcache; \ memoize 'f', LIST_CACHE => [ HASH => \%cache ], \ SCALAR_CACHE =>'MERGE' ; \ for (1..6) { say f() }"
      X73
      X73
      X2
      X2
      X64
      X64
      
      Below is my SerializeValues wrapper. Note that it seems to call the sub-cache's "FETCH" while it stores, effectively reducing NUM_USES by one. Also since Serialize requires a reference, it has to be in the LIST_CACHE slot, not SCALAR_CACHE.
      #!/usr/bin/env perl package SerializeValues; require Tie::Hash; @ISA = qw(Tie::ExtraHash); use strict; use warnings; use Storable qw[freeze thaw]; sub TIEHASH { my ($class, $child_hash) = @_; return bless [$child_hash], $class; } sub STORE { $_[0][0]{$_[1]}= freeze $_[2] } sub FETCH { thaw $_[0][0]{$_[1]} }
      I'm going to email the author (mjd) and suggest adding a flag to the HASH option to say that the values should be serialized first.

      PS. This module is over a decade old, and within a couple weeks two of us independently run into the same limitation- there's something going around...

        Thanks for this example. With a little further modification it demonstrates that Memoize::Expire won't work for functions returning lists
        Right, which is why when I needed such abilities I wrote my own expiring backend to Memoize. If you want to do the same, start with the INTERFACE section of the Memoize::Expire POD.

        For the record, I also had to implement FIRSTKEY and NEXTKEY methods for things to work correctly.

        Cheers.