Let's start with a simple example:
my @input_numbers = (1, 2, 4, 8, 16, 32, 64);
my @result = map $_ + 100, @input_numbers;
For each of the seven items placed into $_, you
get a single output result: the number that is 100 greater than the
input number, so the value of @result is 101, 102,
104, 108, 116, 132, and 164.
But you're not limited to having only one output for
each input. Let's see what happens when each input
produces two output items:
my @result = map { $_, 3 * $_ } @input_numbers;
my %hash = @result;
Or, without using the intermediate array from the map:
my %hash = map { $_, 3 * $_ } @input_numbers;
You can see that map is pretty versatile; you can
produce any number of output items for each input item. And you
don't always need to produce the same number of
output items. Let's see what happens when you break
apart the digits:
my @result = map { split //, $_ } @input_numbers;
Each number is split into its digits. For 1, 2, 4, and 8, you get a
single result. For 16, 32, and 64, you get two results per number.
When the lists are concatenated, you end up with 1, 2, 4, 8, 1, 6, 3,
2, 6, and 4.
If a particular invocation results in an empty list, that empty
result is concatenated into the larger list, contributing nothing to
the list. You can use this feature to select and reject items. For
example, suppose you want only the split digits of numbers ending in
4:
my @result = map {
my @digits = split //, $_;
if ($digits[-1] == 4) {
@digits;
} else {
( );
}
} @input_numbers;
If the last digit is 4, you return the digits themselves by
evaluating @digits (which is evaluated in a list
context). If the last digit is not 4, you return an empty list,
effectively removing results for that particular item. (Thus, a
map can always be used in place of a
grep, but not vice versa.)