Functions¶
Functions are defined using the keyword fn
and must have explicit type annotations.
fn double(x: Int) -> Int {
x * 2
}
Functions can be called using C-style function calls:
double(42)
Void Functions¶
Functions that do not return a value can omit the return type instead of explicitly saying Void
.
fn ignore<T>(x: T) {
// evaluates whatever is passed into `x`, but ignores it's result
}
Currying¶
All the functions are automatically curried, which means that both of the following are equivalent.
fn add(x: Int, y: Int) -> Int {
x + y
}
fn add(x: Int) -> (Int) -> Int {
fn add'(y: Int) -> Int {
x + y
}
}
Both of the add
functions defined above can be called in any of the following ways.
add(3, 5)
add(3)(5)
let add3 = add(3)
add3(5)
Universal Function Call Syntax (UFCS)¶
UFCS allows you to call a function as if was a method of its first argument. Let’s see an example:
fn bool_to_int(x: Bool) -> Int {
if x { 1 } else { 0 }
}
bool_to_int(False) //=> 0 : Int
// Alternatively
True.bool_to_int() //=> 1 : Int
This makes it possible to “extend” a class after its definition.
class C { /* ... */ }
let c = C({})
fn printC(self: C) {
// ...
}
c.printC()
And behaves similar to the reverse application operator in other functional languages like Elm, F# and OCaml (and recently proposed to JavaScript):
list.map(f).filter(g).sort(h).iter(i)
is equivalent to the following in Elm for example:
list |> map f |> filter g |> sort h |> iter i
with the difference that with UFCS the object is passed as the first argument and with the reverse application operator it would be passed as the last argument.