TL;DR

NestedLoops from Algorithm::Loops can come handy. Other functions can too.

In a little side project I ended up with some four or five nested loops and to be honest it seemed a tad too many. Then I remembered about this neat module Algorithm::Loops and in particular the NestedLoops function, that aims at solving exactly that problem.

In my case I just needed to generate the cartesian product of a few input arrays - i.e. I needed all the possible arrangements taking one item from each array. Hence, it can be as simple as this:

use Algorithm::Loops 'NestedLoops';
my @dimensions = (
['A' .. 'F'],          # first slot has some uppercase letters
[ 2, 3, 5, 7 ],        # then some digits
[ qw< foo bar baz > ], # thsn some words
);
NestedLoops(\@dimensions, sub { print join('-', @_), "\n" });


which, as you can correctly guess, prints out $6 \cdot 4 \cdot 3 = 72$ items out:

\$ perl test.pl | nl
1	A-2-foo
2	A-2-bar
...
71	F-7-bar
72	F-7-baz


There are other subtler ways to generate and manage smarter loops… you can get them in the docs, as well as other functions, like:

• the MapCar* family (to iterate over multiple arrays, in parallel)
• NextPermute and NextPermuteNum, which provide iterators to go through all or part of the permutations in a list of elements.

Filter is probably no more needed nowadays after the r non-destructive substitution modifier was added to the s and tr/y operators in 2011.