<- ^ ->

Features of Gont typesystem

4   Features of Gont typesystem

4.1   Functional values

Functions are first class citizens. This functional programming slogan means that you can write a function, that takes function as argument and returns function. For example:

        opt_struct int_list {
                int data;
                int_list next;
        }
        
        *(int_list) -> void mapper(*(int) -> void f) 
        {
                void for_all(int_list lst) 
                {
                        while (lst != null) {
                                f(lst.data);
                                lst = lst.next;
                        }
                }

                return for_all;
        }
This function takes function f operating on items, and returns function that applies f to all elements of list.

The key thing to note is functional type notation. *(int) -> void f means roughly void (*f)(int) -- so it is function that takes single int parameter and returns no value. Similarly *(int, int_list) -> string is function, that takes int and int_list parameter, and returns string.

int_list is passed to functions as pointer (in C's sense).

Functional values are not simply passed as pointers to functions. That wouldn't work for for_all function from our example, since it needs f parameter that would disappear from the stack after mapper has returned. So functional values are passed as pairs of pointers to functions, and pointers to special closure structures.

Nested function definitions (for example the for_all function) are shortcut to defining functional variables and initializing them, so our example could look as:

        *(int_list) -> void mapper(*(int) -> void f) 
        {
                *(int_list) -> void for_all;
                
                for_all = fun (int_list lst) -> void is {
                        while (lst != null) {
                                f(lst.data);
                                lst = lst.next;
                        }
                };

                return for_all;
        }
Or even:

        *(int_list) -> void mapper(*(int) -> void f) 
        {
                return fun (int_list lst) -> void is {
                        while (lst != null) {
                                f(lst.data);
                                lst = lst.next;
                        }
                };
        }
Special extension is supported, useful when dealing with functional values. Whenever function body (sequence of statements within { }) should appear, single expression within ( ) can be supplied. It is passed to return statement, which is only statement in function body. So:

        fun (int a, int b) -> int is (a + b)
is equivalent of

        fun (int a, int b) -> int is { return a + b; }

4.2   Polimorphism

This is probably the neatest thing in Gont. Structures, as well as functions can be parameterized over types. For example to define list of anything you write:

        opt_struct <'a>list {
                'a data;
                <'a>list next;
        }
'a is alpha. It is type variable, it stands for any type (similarly 'b is beta, but I really don't know what 'foo is... :-)

Then you use it as:

        <int>list l;            // list of ints
        <<int>list>list ll;     // list of lists of ints
If you are familiar with C++ you can note `<<' that has to be written as '< <' there. This is not the case in Gont. It is handled specially.

Functions can be written that operate on lists:

        // Call passed function f on each element of the list l
        // starting from head.
        void iter(*('a) -> void f, <'a>list l)
        {
                while (l != null) {
                        f(l);
                        l = l.next;
                }
        }

        // Call function f on each element of the list l,
        // collect results as a list (of possibly different type)
        // and return it.
        <'b>list map(*('a) -> 'b f, <'a>list l)
        {
                <'b>list o = null;

                while (l != null) {
                        o = {data = f(l.data), next = o};
                        l = l.next;
                }

                return o;
        }
Later on you can use defined functions.

Suppose you have defined:

        string int2string(int);
        void print_string(string);
somewhere, then:

        <int>list il = { data = 1, next = { data = 2, next = null }};
        <string>list sl = map(int2string, il);
        iter(print_string, sl);
[[this only works for unions, right now]]

4.3   Tuples

Tuple is datatype, that consists of two or more components, which are anonymous. Tuples are defined as:

        *[int, int] t1;
        *[int, string, bool] t2;
        *[ctx, ty] t3;
And used as:

        t1 = [1, 2];
        int a, b;
        [a, b] = t;
        // swap
        [a, b] = [b, a];
        t3 = [1, "hello", true];
        // true and false are keywords
More on tuples in `Patterns' below.

4.4   Unions

Union are more closely related to ML's datatypes then to C's unions. The basic difference is that Gont compiler remembers which member is currently stored in union.

Unions are defined as:

        union exp {
                int Const;
                string Var;
                *[exp, exp] Add;
                *[exp, exp] Sub;
                *[exp, exp] Mul;
                *[exp, exp] Div;
        }
This union can be later on used for processing symbolic expressions. You can access union components only using pattern matching (there is no `.' notation).

<- ^ ->

Features of Gont typesystem