# June 23 2011: map and grep

`for`

loops are great, but sometimes they feel a bit heavy-handed. Here, let me give an example:

```
my @numbers = 1..10;
my @squares;
for @numbers {
push @squares, $_ * $_;
}
```

You should be comfortable reading code such as the above by now: we populate the array `@squares`

based on the contents of `@numbers`

. The `for`

loop is just to make sure we're visiting each element of `@numbers`

once, and the `push`

adds a new element to `@squares`

as we do that.

We need to do this kind of "array population" quite a bit, so there's a function to help us do that. It's called `map`

:

```
my @numbers = 1..10;
my @squares = map { $_ * $_ }, @numbers;
```

Ah, that's nicer.

The two pieces of code do the same thing. But the block we pass to `map`

need only contain the *transformation* we want to effect. In this case, we want to transform the numbers to their squares. Just as with `for`

, the inside of the `map`

block recognizes the topic variable `$_`

.

What we're passing in to `map`

is, in fact, a little piece of code. We can highlight this fact by extracting the calculation into a subroutine, and pass in the subroutine to `map`

:

```
sub square($n) {
return $n * $n;
}
my @numbers = 1..10;
my @squares = map &square, @numbers;
```

(Yes, that `&`

is a fourth sigil — one for referring to functions. Leaving out the `&`

would call the function before it got a chance to be passed in to `map`

.)

Functions that accept other functions as arguments (or that return functions) are called "higher-order functions". There's a whole programming paradigm built around them — functional programming. I am not kidding.

There's nothing to prevent you from `map`

ping from one element to several, by the way:

```
for map { $_, $_ }, 1..3 {
.say; # "1 1 2 2 3 3"
}
```

There's another higher-order function that we shall go through today: `grep`

. Whereas `map`

*translates* from one whole list to another, `grep`

lets you *filter* elements from a list.

We can start out the same way as with `map`

, by doing it the long way, with a `for`

loop:

```
my @primes;
for 2..100 {
if is_prime($_) {
push @primes, $_;
}
}
say join " ", @primes; # "2 3 5 7 11 13..."
```

So you see, it only includes a number in the `@primes`

array *if* it `is_prime`

.

With `grep`

, it's just this:

```
my @primes = grep { is_prime($_) }, 2..100;
say join " ", @primes; # "2 3 5 7 11 13..."
```

Or even just passing in the function directly:

```
my @primes = grep &is_prime, 2..100;
say join " ", @primes; # "2 3 5 7 11 13..."
```

Oh, the `is_prime`

function? No, it's not built in. I guess I should define it for you:

```
sub is_prime($n) {
return ?($n %% none 2 .. $n - 1);
}
```

[Author's note: go back and add `%%`

to the "Arithmetic" post, apparently we needed it. `:-)`

]

So there we have it. `map`

and `grep`

are higher order functions that help you write common `for`

loops in a shorter way. They help you focus on the code that means things and avoid the code that is always the same every time. Which is nice.