In this session, we are going to cover an important concept in functional programming. Higher order functions let you pass functions as arguments and return them as results. One thing particular about functional languages is that they treat functions as first class values. This means that. Like any other value a function can be passed as a parameter to another function or returned as a result. We'll see in this session that this provides a flexible way to compose programs. Functions that take other functions as parameters, or that return functions as results are called higher order functions. So, that's the opposite of first order functions. A first order function would be, then, a function that acts on data types, simple data types such as [inaudible] or longs or lists, but not other functions. Whereas, a higher order function acts on other functions. Let's see an example. Let's suppose we want to take the sum of all the integers between a and b. So we could write something like this. Sum iints, it takes the, the bounds as parameters, the and the b. And we ask well, if a is greater than b, then there is nothing to sum. And we would return zero as the, logical value for that. And otherwise we would return a + a recursive call of sum ints of a+1 and b. Good. Now that we've done that, let's vary the problem a little bit and consider taking the sum of the cubes of all integers between a and b. So here's the cube function. Take an x, return x times x times x. Some cubes then would be the same as some ints. But, where we used an A before now we return cube of A. And otherwise, it's the same thing as some ints. Recursive call to sum cubes in this case. Next, let's take the sum of all factorials of the integers between a and b. Well, you see the principle by now. The program, again, is exactly like sum ints and sum cubes, except that where previously we computed the q, we compute the factorial. Of course, these are all special cases of the mathematical sum of the values of f of n, where f is the given function, and n is taken from the interval between a and b. The questions is, well if mathematics has a special notation for that, shouldn't programming have one as well. Can we factor out the common pattern into a single method. So here's how that's done. Let's define a function sum which takes a parameter F of type INT to INT, and to two bounds A and B, both INTs. And let's generalize the previous, three definitions as follows. We write, if A greater than B, then zero, otherwise, take F of A plus sum of F and A plus one. B. So the new thing here is that F is a parameter of the sum function. It's not a given function. It's a parameter. Once we have that, we can then write our function sum in sum cube, sum factorial as follows. Sum. Ints would be simply sum of id of ab, where the id function simply returns its parameter unchanged. Sum cubes would be sum of cube and AB, where the cube function is as what we've seen before. And finally, sum factorial is sum of fact and AB, where the fact function is, again, the factorial function. So what we've done, effectively, is reuse the pattern that defines the sum function, so that we had to write that only once. And we could reuse it in the three definitions of the particular sums. One thing that's new here is a function type. Function type is written A aero B, where A and B are types. And its a type of a function that takes some argument of type A, and returns a result of type B. So for example Int aero Int, is a type of functions that map integers to integers. Looking at the previous example again, we have successfully shortened the definition of some ins, some cube, some factorials. But there's an annoying detail. You have to name all the little auxiliary functions that we do here. So, we've gained some eh, programme called here but we've spent more in the definition of all these auxiliary functions. So we've seen that passing functions as parameters can lead to the creation of many small functions, and sometimes that's tedious. Compare the situation to other types such as strings. We could write something like Def STR equals ABC and then print an STR, But we don't have to. We can just as well write print on ABC directly and that's because strings exist as literals. Since functions are important in our language, it makes sense to think of introducing literals for functions as well, and that's what we do next. These literals are called anonymous functions, because they do not have a name. So here is how we write anonymous functions. There is an example let's consider the function that raises this argument to a cube that would be written as you see here, sorry, takes a parameter X of type int, and then there comes an arrow and then comes the value of the function In this case, case X times X times X. So X colon INT is the parameter of the function, and on the right hand side of the arrow is the body. In fact, the type of the parameter can be omitted if the compiler can infer it from the context. And if you have several parameters, you can write them in a list separated by commas. So, for instance, that function here. What would that be? Well yes the summation functions so it would take two integers X and Y, and give you the sum of X and Y. You could ask, are anonymous function essential for Scalar? Just as, let's say, conditionals or value definitions are essential. Or can they be defined in some other way? It actually, it turns out that every anonymous function can be expressed in some other way, using a def. So let's say you have an anonymous function with n parameters x1 to xn and a body e. You can always write this as the function def f. Then come the parameters, then comes the body, and then you follow that by a reference to this function that you have just defined. Sometimes you might have to write the expression in a block, so that it, it doesn't, the name doesn't get confused with something else. Because we can always rewrite anonymous functions, we can therefore say that they are syntactic sugar. They make writing functions sometimes easier, but they're not essential in the sense that they do not add anything to the fundamentally expressive power of the language. So to come back to the sum INTs and sum cubes example, using anonymous functions, we can write these now in a shorter way. Sum INTs would be just the function sum, where the function we pass is the identity function, written X arrow X, and to balance our, the parameters, and sum cubes would have as the function parameter X arrow X times X times X. And if we do that, then we do not need anymore the auxiliary definitions of identity or cube. Let's do an exercise. The sum function uses linear recursion, can you write a tail recursive function instead? Note that, unlike factorial, some really could profit from this tail recursion optimization. Because of the interval between A and B is large, you might get a lot of different recursive steps so you might risk a stack overflow. So let's rectify that, and design a tail recursive function instead. I've already given you a template for this function. It uses a nested function loop. And all you have to do is replace the triple question marks here and here. So let's see how we would go about that. The first one here is we, in the loop function we have a test that says well if something is true then probably that would be the termination. So when do we terminate. Well we terminate if the lower bound A is greater then the upper bound B. And what do we return in that case? Well, since we have used the accumulator trick, we would return the accumulator. Once we have that, we can look at the initial call, so as the first parameter, we would pass the initial lower bound A. And as the initial accumulator would have to be what. Well, we know accumulator is the result that we return, and the interval is initially empty, so that would have to be zero. And finally, in the recursive call, we would assume that the initial bound gets incremented by one. And the new accumulator is F applied to A plus the previous accumulator. You can test this function. Let's apply this function to lower bound three, upper bound five. And you would get 50, as expected. You have seen higher order functions as essential building blocks of functional programs. In the next session we are going to play a little bit more with higher order functions and introduce new ways to express them.