Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

ferreira (5993)

ferreira
  (email not shown publicly)
http://www.ferreira.triang.net/

Just another Brazilian Perl hacker.

Journal of ferreira (5993)

Wednesday March 05, 2008
03:13 PM

Abusing "Memoize"

[ #35842 ]

A few days ago, I was writing a code (namely the Path-Classy dist) and stared at the code that produced the file size in raw bytes or "humanized" (28300 or 28K).

sub _format_size {
  my ($sz, $opt) = @_;

  my $format = $opt->{format};
  if ( $format eq 'h' ) {
    require Numbers::Bytes::Human;
    return Number::Bytes::Human->new->format( $sz );
  }
  else { # raw bytes
    return $sz;
  }
}

Of course, loading Number::Bytes::Human and creating a instance every time $f->size({ format => 'h' }) was invoked seemed overkill. But saving the N::B::H into a class/instance variable seemed overkill too: it has nothing to do with Path::Classy (which are Path::Class ) objects but for that instant relationship to format a file property, size.

Hey, that's a chance to use memoization, splitting the formatter creation into a function and then memoizing it (so that we don't need to create a [reusable] object with the same capabilities over and over), we come to this code.

use Memoize;

sub _size_formatter {
  require Number::Bytes::Human;
  return Number::Bytes::Human->new;
}
memoize('_size_formatter');

sub _format_size {
  my ($sz, $opt) = @_;

  my $format = $opt->{format};
  if ( $format eq 'h' ) {
    return _size_formatter->format( $sz );
  ...

That looked elegant to me. To make it even more tight (and to require yet another CPAN module ;-) ), using Attribute::Memoize seemed right. It avoids the need to repeat the function name in the memoize call and it anticipated the wrapping up of the sub to BEGIN time (a free bonus of Attribute::Handlers in the backstage).

use Attribute::Memoize;

sub _size_formatter :Memoize {
  require Number::Bytes::Human;
  return Number::Bytes::Human->new;
}

That's it! Efficient code, localized behavior, no need for extra variables. Will people understand that for maintenance? I hope so.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.