Declaring a function¶
fn declares a named function: a name, typed parameters, a result type and a
body. fn days(pages: Int, per_day: Int) : Int gives days the type
(Int, Int) -> Int.
fn days(pages: Int, per_day: Int) : Int = (pages + per_day - 1) / per_day
[days(412, 40), days(280, 40)]
[11, 7]
Every parameter has a type and the result type is written. Each call is checked against them before the program runs:
fn days(pages: Int, per_day: Int) : Int = (pages + per_day - 1) / per_day
days("412", 40)
check error[type-mismatch]: this argument is String, and parameter `pages` takes Int
--> <expression>:2:6
|
2 | days("412", 40)
| ^^^^^
The body after = is one expression. A body may also be a block of named
steps, in braces; Function bodies covers both forms.
A function by its name¶
Naming a declared function where a function is expected passes it as a
value, xs | map(f). Its name is bound before its body is checked, so it may
call itself:
fn factorial(n: Int) : Int = 1 given n <= 1 otherwise n * factorial(n - 1)
[1, 2, 3, 4, 5] | map(factorial)
[1, 2, 6, 24, 120]
Functions taken and returned¶
A parameter may have a function type, and so may the result. A returned function keeps the values it captured:
fn adder(k: Int) : Int -> Int = n => n + k
fn twice(f: Int -> Int, x: Int) : Int = f(f(x))
twice(adder(3), 30)
36
Variadic parameters¶
A last parameter written ...T collects any number of trailing arguments into
a list:
fn total(xs: ...Int) : Int = xs | sum
[total(), total(1, 2), total(1, 2, 3, 4)]
[0, 3, 10]
A result that may be missing¶
Option<T> is the result type of a function whose value may be absent.
some(x) and none build one, match takes one apart, and somes keeps the
present values of a collection:
fn rating_of(r: Int) : Option<Int> = some(r) given r > 0 otherwise none
[5, 0, 4] | map(rating_of) | somes
[5, 4]
Option has the rest of Option's operations.