Friday, November 26, 2010

Memoizing an object method

It took me a while to find out how to do that in Perl. I am now sharing this little bit of Perl magic with you.

Basically first you have to create a reference to a method capturing the current object in a closure.

$obj = new Class(...);

$callback = sub { $obj->method(...) };

When you memoize a reference you simply get a new one pointing to the memoized version of the function and use that from now on:

$cached_callback = memoize($callback);

$cached_callback->();
$cached_callback->();

This will allow you implement a caching mechanism for your classes as a breeze!

Perl's motto should be changed to "There is always a (simple) way to do it". This should shut up all the people who think that Perl is overcomplicated. One may say that pure OO languages are better. It is an old dispute. Maybe for some tasks. But generally poor pure OO (e.g. Java) languages won't take you far.

Full demo showing parameter passing:

memoize.pl
#!/usr/bin/perl

use strict;
use warnings;

use Memoize;

use lib '.';
use Class;

my $test = new Class();

my $callback = sub {
    $test->bumpup($_[0]);
};

my $cached_callback = memoize($callback);

# actual call, inc=1
# 2
print $cached_callback->(1), "\n";

# 2
print $cached_callback->(1), "\n";

Class.pm
use warnings;

package Class;

my $var = 1;

sub new {
    bless {};
}

sub bumpup {
    my ($obj, $inc) = @_;

    print "actual call, inc=$inc\n";

    $var += $inc;
}

1;

No comments: