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;