Here's how it emerged:
Just as an exercise, I wanted to generate a list of strings with a specific length from every possible combination of a list of characters.
But not with for loops, but with nested maps! In its simplest form, with 2 chars and strings with a length of two:
my @a = qw( a b ); my @b = map { my $x = $_; map { $x . $_ } @a; } @a;
This produces aa, ab, ba, bb.
Adding characters is easy:
my @a = qw( a b c );
This produces aa, ab, ac, ba, bb, bc, ca, cb, cc.
But increasing the length of the string is not so easy. I did this by adding another nested map:
my @b = map { my $x = $_; map { my $y = $_; map { $x . $y . $_ } @a; } @a; } @a;
which, with qw( a b ), produces aaa, aab, aba, abb, baa, bab, bba, bbb. This is, of course, stupid.
One way to solve this problem is with a recursive function:
sub f { my ( $n, @a ) = @_; croak "illegal value for n: $n" if $n < 1; return @a if $n == 1; map { my $x = $_; map { $x . $_ ) } f( $n - 1, @a ); } @a; }
Now you could make it more general by adding a coderef parameter, string concatenation being only a special case needed in the original example:
sub f { my ( $n, $g, @a ) = @_; croak "illegal value for n: $n" if $n < 1; return @a if $n == 1; map { my $x = $_; map { $g->( $x, $_ ) } f( $n - 1, $g, @a ); } @a; }
So we have a function f that produces a list b by applying a function g to all possible combinations of a list a by calling itself recursively n times.
Is this useful? Or could it be further transformed so that it yields something useful?
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: nested maps
by bobf (Monsignor) on Apr 26, 2007 at 13:20 UTC | |
|
Re: nested maps
by Limbic~Region (Chancellor) on Apr 26, 2007 at 13:28 UTC | |
by jczeus (Monk) on Apr 26, 2007 at 15:12 UTC | |
|
Re: nested maps
by Fletch (Bishop) on Apr 26, 2007 at 13:13 UTC | |
by jczeus (Monk) on Apr 26, 2007 at 14:49 UTC | |
|
Re: nested maps
by DrHyde (Prior) on Apr 27, 2007 at 08:48 UTC | |
by raygun (Scribe) on Sep 20, 2020 at 00:25 UTC | |
by LanX (Saint) on Sep 20, 2020 at 18:14 UTC | |
by LanX (Saint) on Sep 21, 2020 at 11:37 UTC | |
by tobyink (Canon) on Sep 21, 2020 at 13:18 UTC | |
|