Functions¶
Functions encapsulate calculations.
Definition by Expression¶
A function can be defined by an expression:
fun square (x:int) : int => x * x;
or without the return type:
fun square (x:int) => x * x;
in which case it is deduced.
Definition by Statements¶
More complex functions can be defined by statements.
fun addUp(xs:int^4) : int = {
var sum = 0;
for x in xs do
sum = sum + x;
done
return sum;
}
The return type can be elided:
fun addUp(xs:int^4) = {
var sum = 0;
for x in xs do
sum = sum + x;
done
return sum;
}
No side effects¶
The effect of a function must be entirely captured in its returned value; that is, it may not have any side effects. This asumption is currently not checked, so you could write code like this:
var mutMe = 0;
fun addUp(xs:int^4) : int = {
mutMe = 1; // bad!
var sum = 0;
for x in xs do
sum = sum + x;
done
return sum;
}
However, this kind of usage may be useful from time to time, for example for debugging.
The lack of side effects in a function are used in optimizations,
and the optimizations may have an effect on program behavior.
For example, the following toy program takes the second projection
(. 1
) on a tuple involving three function calls. Since functions
are assumed to have no side effects, the other function calls
(f
and h
) are erased as their return values are never used.
fun f(x:int) = {
println "hi from f!";
return 2*x;
}
fun g(x:int) = {
println "hi from g!";
return 3*x;
}
fun h(x:int) = {
println "hi from h!";
return 4*x;
}
val res = (f 5, g 5, h 5) . 1;
println res;
The output of the program is just:
hi from g!
15
Purity¶
Functions can further be annotated to be pure
or impure
, but at the
moment, the semantics of these are not defined and are not checked:
pure fun addUp(xs:int^4) : int = {
// ...
}
// or
impure fun addUp(xs:int^4) : int = {
// ...
}