## Functions

In a model, computations must be performed to process the information that is sent around. Short and simple calculations are written as assignments between the other statements, but for longer computations or computations that are needed at several places in the model, a more encapsulated environment is useful, a function. In addition, the language comes with a number of built-in functions, such as `size` or `empty` on container types. An example:

    func real mean(list int xs):
        int sum;

        for x in xs:
            sum = sum + x
        end;
        return sum / size(xs)
    end

The `func` keyword indicates it is a function. The name of the function is just before the opening parenthesis, in this example `mean`. Between the parentheses, the input values (the formal parameters) are listed. In this example, there is one input value, namely `list int` which is a list of integers. Parameter name `xs` is used to refer to the input value in the body of the function. Between `func` and the name of the function is the type of the computation result, in this case, a `real` value. In other words, this `mean` function takes a list of integers as input, and produces a `real` value as result.

The colon at the end of the first line indicates the start of the computation. Below it are new variable declarations (`int sum`), and statements to compute the value, the function algorithm. The `return` statement denotes the end of the function algorithm. The value of the expression behind it is the result of the calculation. This example computes and returns the mean value of the integers of the list.

Use of a function (application of a function) is done by using its name, followed by the values to be used as input (the actual parameters). The above function can be used like:

    m = mean([1, 3, 5, 7, 9])

The actual parameter of this function application is `[1, 3, 5, 7, 9]`. The function result is `(1 + 3 + 5 + 7 + 9)/5` (which is `5.0`), and variable `m` becomes `5.0`.

A function is a mathematical function: the result of a function is the same for the same values of input parameters. A function has no side-effect, and it cannot access variables outside the body. For example, it cannot access `time` (explained in Servers with time) directly, it has to be passed in through the parameter list.

A function that calculates the sign of a real number, is:

    func int sign(real r):
        if r < 0:
            return -1
        elif r = 0:
            return  0
        end;
        return  1
    end

The sign function returns:

- if `r` is smaller than zero, the value minus one;

- if `r` equals zero, the value zero; and

- if `r` is greater than zero, the value one.

The computation in a function ends when it encounters a `return` statement. The `return 1` at the end is therefore only executed when both `if` conditions are false.

### Sorted lists

The language allows recursive functions as well as higher-order functions. Explaining them in detail is beyond the scope of this tutorial, but these functions are useful for making and maintaining sorted lists. Such a sorted list is useful for easily getting the smallest (or largest) item from a collection, for example the order with the nearest deadline.

To sort a list, the first notion that has to be defined is the desired order, by making a function of the following form:

    func bool decreasing(int x, y):
        return x >= y
    end

The function is called predicate function. It takes two values from the list (two integers in this case), and produces a boolean value, indicating whether the parameters are in the right order. In this case, the function returns `true` when the first parameter is larger or equal than the second parameter, that is, larger values must be before smaller values (for equal values, the order does not matter). This results in a list with decreasing values.

The requirements on any predicate function `f` are:

1. If `x != y`, either `f(x, y)` must hold or `f(y, x)` must hold, but not both. (Unequal values must have a unique order.)

2. If `x == y`, both `f(x, y)` and `f(y, x)` must hold. (Equal values can be placed in arbitrary order.)

3. For values `x`, `y`, and `z`, if `f(x, y)` holds and `f(y, z)` holds (that is `x >= y` and `y >= z`), then `f(x, z)` must also hold (that is, `x >= z` should also be true).

(The order between `x` and `z` must be stable, even when you compare with an intermediate value `y` between `x` and `z`.)

These requirements hold for functions that test on `<=` or `>=` between two values, like above.

If you do not provide a proper predicate function, the result may not be sorted as you expect, or the simulator may abort when it fails to find a proper sorting order.

#### Sort

The first use of such a predicate function is for sorting a list. For example list `[3, 8, 7]` is sorted decreasingly (larger numbers before smaller numbers) with the following statement:

    ys = sort([3, 8, 7], decreasing)

Sorting is done with the sort function, it takes two parameters, the list to sort, and the predicate function. (There are no parentheses `()` behind `decreasing`!) The value of list `ys` becomes `[8, 7, 3]`.

Another sorting example is a list of type `tuple(int number, real slack)`, where field `number` denotes the number of an item, and field `slack` denotes the slack time of the item. The list should be sorted in ascending order of the slack time. The type of the item is:

    type item = tuple(int number, real slack);

The predicate function `spred` is defined by:

    func bool spred(item x, y):
        return x.slack <= y.slack
    end

Function `spred` returns `true` if the two elements are in increasing order in the list, otherwise `false`. Note, the parameters of the function are of type `item`. Given a variable `ps` equal to `[(7, 21.6), (5, 10.3), (3, 35.8)]`. The statement denoting the sorting is:

    qs = sort(ps, spred)

variable `qs` becomes `[(5, 10.3), (7, 21.6), (3, 35.8)]`.

#### Insert

Adding a new value to a sorted list is the second use of higher-order functions. The simplest approach would be to add the new value to the head or rear of the list, and sort the list again, but sorting an almost sorted list is very expensive. It is much faster to find the right position in the already sorted list, and insert the new value at that point. This function also exists, and is named `insert`. An example is (assume `xs` initially contains `[3,8]`):

    xs = insert(xs, 7, increasing)

where `increasing` is:

    func bool increasing(int x, y):
        return x <= y
    end

The `insert` call assigns the result `[3,7,8]` as new value to `xs`, `7` is inserted in the list.