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