Internal user-defined functions

The most commonly used kind of user-defined functions are the internal user-defined functions. Consider the following CIF specification:

func real mean(list real vs):
  int length = size(vs);
  int index = 0;
  real sum = 0;

  while index < length:
    sum := sum + vs[index];
    index := index + 1;
  end
  return sum / length;
end

This specification defines a function (keyword func) named mean. After the name of the function, between the parentheses, the parameters are listed. The parameters are the input values, which the function can use to compute its result. In this example, the function takes a list of real values as its only parameter. Parameter name vs can be used in the body of the function to refer to this input value. Just after the func keyword, the type of the result of the computation is specified. In this case, the function results in a real typed value. The mean function takes a list of integer values and produces a single real value as result.

In the body of the function, local variables can be declared. The mean function declares three variables: length, index, and sum. Local variables of functions are very similar to discrete variables. The main difference is that they are declared without the disc keyword. In the example, length is set to the number of elements in list vs. Variables index and sum are both initialized to 0.

After the local variables (if any), the statements of the body are given. The statements implement the algorithm, the actual computation of the function. Statements are executed one after another, in the order they are given. In the mean function, the while statement is executed before the return statement. The mean function first calculates the sum of the input values, and then returns the mean value. The details of the statements are discussed in the next lesson.

A function can be called (or applied) on concrete input values, to obtain the computation result for those specific input values. For instance, consider the following extension to the above CIF specification:

alg real m = mean([1.5, 3.2, 7.9, 15.8]);

automaton a:
  disc real x;

  location:
    initial;
    edge do x := 2 * mean([0.4, 1.5, 6.8]);
end

Algebraic variable m is given the value that results from calling function mean on a single argument, a list with four values. Each argument of a function call must match with the corresponding parameter of the function being called. In this case, the list of four real values matches with the vs parameter of the mean function, which has type list real. Variable m becomes 7.1, as the mean of those four values is 7.1 ((1.5 + 3.2 + 7.9 + 15.8) / 4).

The edge in automaton a assigns a value to variable x. The mean of a list of three values is calculated, and multiplied by two, to obtain the new value of x. The mean of 0.4, 1.5, and 6.8 is (0.4 + 1.5 + 6.8) / 3, which is 2.9. Variable x gets 5.8 (2.9 * 2) as its new value.

Function mean is called in two places in the example, showing reuse of calculations.

Functions in CIF are mathematical functions. That is, the result of a function is the same for the same input values, and functions have no side effects. Functions can not directly access variables outside their body. For example, they cannot access discrete, continuous, and algebraic variables. They can also not use variable time. To use the values of those variables in a function, they have to be passed in through parameters.