So far, All operations on lists were first order.

That means, the functions took lists of primitive types as arguments and returned

them as results. In this session, we're going to change

that. We're going to introduce higher order list

functions that work on lists and take another function as argument.

We will see that with just a handful of these higher order functions, we can

describe a great variety of different tasks.

The examples in the previous sessions have shown that functions of lists often have

very similar structure. In fact, we can identify several recurring

patterns, such as transforming each element in a list in a certain way,

Or retrieving from a list all elements that satisfy a given criterion, or maybe

combining the elements of a list using an operator.

And since we are in a functional language which allows programmers to write generic

functions using high auto-functions, we can apply the same techniques to functions

over the lists. So in this session, we are going to be

interested in higher order functions over the lists.

Our first common operation is to transform each element of a list, and then return

the list of results. So for instant to multiply each element of

a list by the same factor, you could write a function scale list which takes a list

of doubles as input and a factor and returns a list of double and what it does

is, well if the input list is nil, it just returns it unchanged, and otherwise it

multiplies the first element of the list by the factor, and it does a recursive

call of scale list with the rest of the list and factor.

So, obviously, that function would multiply each element of the list by the

same factor. That scheme can be generalized to a method

map on the list class which can apply in arbitrary operation to all elements of a

list. So here's a simple way to define map on

the abstract class list of t. We would say def map and map takes a

function from t to some. Other type, u, which could be the same as

type t, or it could be different. So, u is a type parameter of MAP.

And then it returns a list of u. And then the body of MAP is just the body

of scale lists, but now generalized. So, in the case of nil, we return the list

unchanged. If the list is non-nil, then we apply the

function, F to the first element X,

And we follow that with a recursive call of xs.mapf.

In fact the actual implementation of map N class list and this kind of standard

library is a bit more complicated for several reasons.

First, the actual definition is in fact terra cursive.

Where as this definition isn't you see after the call to map you still have a

call to cons. The second the actual implementation to

maps for arbituary collections not just lists.

But for understanding map list definition here we'll do very well.

So using map, we can now write scale list much more concisely, so much more

concisely that, that it's hardly worth writing a different function for it.

We would just say, scale list of XS and a factor S, map XS map, with the function

that takes an X and multiplies X by the factor.

So here's an exercise for you. Let's take a function square list that

squares each element of a list, then returns the result.

There are two possible ways to do that, either with pattern matching or using map.

I invite you to try both possible ways by filling in the three triple question marks

in the definition of square lists here and the definition of square lists down there.

So let's see how we would do that. In the paren.

Matching definition to take the squares of an empty list we would surely return the

empty list again. To take the squares of a list with a head

y and a tail ys, what do we do? Well, we start by taking the square of y

and we follow that by a recursive call of square list.

Of Y-S. So far so good.

I think by now we all know how to do these things cold.

But, let's see whether we can do it shorter using map.

Well, to use square list with map, what can we do?

Well, we map it by the function that takes an X, and returns X times X.