Previous Page
Next Page

19.11. Memoization

Automate your subroutine caching.

The logic required to implement a caching strategy is always the same: check whether the result is already cached; otherwise, compute and cache it; either way, return the cached result. So, as usual, there's a CPAN module that automates the task: Memoize.

To add caching to a subroutine (a process called memoization), you simply define the subroutine without any caching, and load Memoize. The module will automatically export a memoize( ) subroutine, which you then call, passing it a string containing the name of the subroutine you want cached. Like so:

    sub lc_digest {
        my ($text) = @_;

        use Digest::SHA qw( sha512 );
        return sha512(lc $text);

    use Memoize;
    memoize( 'lc_digest' );

Notice how much cleaner this is than the "manually cached" version in Example 19-9.

It's also more reliable, as you can focus on getting the computation correct, and leave the details of the caching strategy to Memoize. For example, the caches that the module installs correctly differentiate between subroutine calls in list and scalar context. This is important, because the same subroutine called with the same arguments might still return different values, depending on whether it was expected to return a list or a single value. Forgetting this distinction is a very common error when implementing caching manually[*].

[*] It's not, however, a defect in the manually cached version of lc_digest( ) in Example 19-9, because sha512( ) always returns a single value, regardless of its call context.

The memoize( ) subroutine has many other options for fine-tuning the kinds of caching it confers. The module documentation provides detailed descriptions of the many possibilities, including caching results in a database so that the cache persists between executions of your program.

    Previous Page
    Next Page