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 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; }