2011
08.03

Combining the powers of parts 3 and 4, we are ready for higher order functions.

Basically, a higher order function is a function that expects a function as an argument.

In part 4, we defined a function that can add up a bunch of numbers, regardless of how many there are. It is highly likely that we would like to perform a similiar operation on a data structure in the future, but with – say – multiplication. What we would like is a function that will operate on data in a certain way, but with a combiner function the caller could plug in.

Reduce

In fact, such a function is already provided with this technology preview. It is called ‘Reduce’, and it resides in the package ‘Algorithm’. Import algorithm.k to be able to use it, like so:

PS C:\Users\Vesa\Kronos.Preview1> .\k2cli.exe .\algorithm.k
K2CLI 0.1
(c) 2011 Vesa Norilo

EXPR>Algorithm:Reduce(Add 1 2 3 4 5)
Algorithm:Reduce(Add 1 2 3 4 5) => 15
EXPR>Algorithm:Reduce(Mul 1 2 3 4 5)
Algorithm:Reduce(Mul 1 2 3 4 5) => 120

Here we perform two reductions on the set (1 2 3 4 5); first by adding the numbers, then by multiplying them. Reduce accepts a function parameter, here supplied as either ‘Add’ or ‘Mul’. Slightly less intuitively;

EXPR>Algorithm:Swap(1 2)
Algorithm:Swap(1 2) => (2 1)
EXPR>Algorithm:Reduce(Algorithm:Swap 1 2 3 4 5)
Algorithm:Reduce(Algorithm:Swap 1 2 3 4 5) => (5 4 3 2 1)

‘Reduce’ is highly general; as you learn functional programming, you will continuously come up with new things you can do with it.

Map

Another highly general function is Map; likewise defined in algorithm.k and allowing you to perform a function repeatedly on a number of elements.

EXPR>Algorithm:Map(Sqrt 1 2 3 4 5)
Algorithm:Map(Sqrt 1 2 3 4 5) => (1 1.41421 1.73205 2 2.23607)

Here, we take a square root of each item in the argument and provide a result as a list.

Suppose we have a function of our own? That is also fair game for Map and Reduce;

PS C:\Users\Vesa\Kronos.Preview1> .\k2cli.exe .\algorithm.k .\part3-myfunc.k
K2CLI 0.1
(c) 2011 Vesa Norilo

EXPR>Algorithm:Map(Take-Square 1 2 3 4 5)
Algorithm:Map(Take-Square 1 2 3 4 5) => (1 4 9 16 25)

Here we import both algorithm.k and the very first function we implemented, and use that as the mapping function. Same goes for Reduce – however, note that the function passed to Map should operate on a single argument, while Reduce expects a binary or two-argument function.

Anonymous functions

It is not necessary to give a separate function definition to obtain something you can pass to Map or Reduce. Using a quote, you can denote a part of your program as an anonymous function.

EXPR>Algorithm:Map('Add(arg 100) 1 2 3 4 5)
Algorithm:Map('Add(arg 100) 1 2 3 4 5) => (101 102 103 104 105)

Here, we quote a function that adds 100 to its argument. In anonymous functions, the reserved symbol ‘arg’ is always bound to the entire argument (it may, therefore, be a list of things as well).

Summary

Higher order functions provide constructs that replace loops and iterations in procedural languages. They are arguably more flexible, and provide you ways to write efficient code.

Equipped with the basics, we are finally going to produce some audio in part 6.

 

No Comment.

Add Your Comment


seven − = 1