1 package MiniMemoize;
2 use Exporter;
3 @ISA = qw(Exporter);
4 @EXPORT = qw(memoize);
5 use Carp;
6 use strict;
7
8 my %memotable;
9
10 sub memoize {
11 my $function = shift;
12 my $funcname;
13 if (ref $function eq '') {
14 my $caller = caller;
15 # Convert to code reference
16 $function = $caller . "::$function" unless $function =~ /::/;
17 $funcname = $function;
18 no strict 'refs';
19 $function = \&$function;
20 }
21
22 my $stub = eval qq{sub { _check_cache("$function", \@_) }};
23 $memotable{$function} =
24 { original => $function,
25 cache => { },
26 };
27
28
29 { no strict 'refs';
30 *{$funcname} = $stub if defined $funcname;
31 }
32 $stub;
33 }
34
35
36 sub _check_cache {
37 my $what_func = shift;
38 unless (exists $memotable{$what_func}) {
39 # This `should never happen'
40 croak("Tried to check cache of non-memoized function `$what_func'; aborting");
41 }
42
43 my $cache = $memotable{$what_func}{cache};
44 my $argstr = join $;, @_;
45 if (exists $cache->{$argstr}) { return $cache->{$argstr} }
46
47 my $real_function = $memotable{$what_func}{original};
48 $cache->{$argstr} = $real_function->(@_);
49 }
50
51 1;