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 {
    putStr("Enter a radius: ");
    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
Enter a radius: 5
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
*/

Recent Comments

No comments to show.

Pages