# Basic functions

B

Functions are the basic components of Kaya programs. They are defined by the following general scheme (the expression may be made up of many statements):

``````ReturnType functionName(arg1Type arg1name, ...) {
expression;
}``````

A simple example is this function, which totals its arguments:

``````Int total(Int a, Int b, Int c) {
return a+b+c;
}``````

A more complex example, which also demonstrates recursion (functions calling themselves) is the following function, which finds a number in the fibonacci sequence in an inefficient way.

``````Int fib(Int x) {
if (x == 0 || x == 1) {
return 1;
} else {
return fib(x-2)+fib(x-1);
}
}``````

Functions are ‘first-class’ objects, and so have types and can be passed as variables. For example, the type of `fib` is `Int(Int)` and the type of `total` is `Int(Int,Int,Int)`. The following function tests if all elements of an array match a user-supplied condition.

``````Bool allMatch([Int] xs, Bool(Int) test) {
// allMatch (hopefully obviously) has the type Bool([Int],Bool(Int))
for x in xs {
if (!test(x)) {
return false;
}
}
return true;
}``````

This function could be used like this:

``````Void main() {
allMatch([1,3,9,5,4,11],odd);
}

Bool odd(Int num) {
return (num % 2 != 0);
}``````

## Constant functions

For convenience, functions that take no arguments can have the brackets omitted. This is intended to allow you to represent constant values.

``````program piprog;

import IO; // For the "get" function.

Float Pi {
return 3.14159265358979;
}

Void main {
r = Float(get(stdin));
putStrLn("Area is " + String(Pi*r*r));
}``````

Note that

`stdin` is another constant function, which returns the standard input stream. Running this program gives:

```\$ ./piprog
Area is 78.5398
\$```

A further shorthand for constant functions is

``Float Pi = 3.141592653589793;``

This is not a global variable, as it cannot be modified.

## Function parameters

Function parameters are normally passed as a shallow copy (i.e. the parameter itself is copied, but references inside are not. Therefore:

``````Void increment(Int a) {
a = a+1;
putStrLn("a = "+a);
}

Void main() {
a = 5;
increment(a);
putStrLn("a = "+a);
}

/* output is
a = 6
a = 5
*/``````

Incrementing the variable inside the function does not affect its value outside the function. However, because it’s only a shallow copy:

``````Void increment([Int] a) {
a[0] += 1;
putStrLn("a[0] = "+a[0]);
}

Void main() {
a = [5];
increment(a);
putStrLn("a[0] = "+a[0]);
}

/* output is
a[0] = 6
a[0] = 6
*/``````

To avoid modifying the values ‘inside’ a parameter, you can use the copy function from the standard prelude to make a deep copy of the parameter. (Warning: this can be very slow for complex data structures, and is usually unnecessary)

``````Void increment([Int] a) {
a[0] += 1;
putStrLn("a[0] = "+a[0]);
}

Void main() {
a = [5];
increment(copy(a));
putStrLn("a[0] = "+a[0]);
}

/* output is
a[0] = 6
a[0] = 5
*/``````

Conversely, if you would like the function to be able to completely modify its parameters, you can use the `var` keyword to pass by reference.

``````Void increment(var Int a) {
a = a+1;
putStrLn("a = "+a);
}

Void main() {
a = 5;
increment(a);
putStrLn("a = "+a);
}

/* output is
a = 6
a = 6
*/``````