I’ve been reading more and more about functional programming over the past year, and working in Python where many things are immutable, and I’m trying to incorporate them into my Perl code.

Probably the biggest influence of functional is that I try to call as few verbs as possible. For example, here’s some code from my codebase at work.

my @got;
push(@got, 'books')      if ($list->bwanted > 0);
push(@got, 'eBooks')     if ($list->ewanted > 0 and $user->can_order_ebooks eq 'Y');
push(@got, 'A/V items')  if ($list->awanted > 0);

That’s three different calls to push in three lines of code that are very similar to each other. We shouldn’t need to do that.

The pattern here is that we push the string on the left into @got if the condition on the right is true. I created a function called map_x_if_y to handle this, letting me rewrite the lines above as:

my @got = map_x_if_y(
    'books'     => ($list->bwanted > 0),
    'eBooks'    => ($list->ewanted > 0 and $user->can_order_ebooks eq 'Y'),
    'A/V items' => ($list->awanted > 0),
);

Now I have no instances of push, and I’m just declaring conditions and results. Any work being done is hidden inside a function. I’m only setting the contents of @got one time, and the focus is on the data.

The function itself is very simple:

use List::Util qw( pairmap );

sub map_x_if_y {
    return pairmap { $b ? ($a) : () } @_
}

I’m not very happy with the name map_x_if_y. Please email me if you have ideas for a better name, or if there’s a standard name for this operation.

I was happy with this refactoring, but then it got better. When I ran the perlcritic code analyzer on the original .pm file, I was helpfully informed that “@got is declared but not used at line…” The only code that’s better than cleaned-up code is code that I can throw away!

I got the new message because I had the Variables::ProhibitUnusedVarsStricter policy installed, and since there was now only one place where @got was being referenced, the policy knew that it was not being used.

Another win for thinking functional, and another win for running perlcritic often.