Functions
Basic Functions
Functions are declared with fn. The body follows a colon and is indented:
fn add(x: i64, y: i64) -> i64:
x + y
No return type means the function returns unit:
fn greet(name: String):
print(name)
Short functions can be written inline:
fn double(x: i64) -> i64: x * 2
fn apply(x: i64) -> i64: compute(x)
Generics
Type parameters go in angle brackets after the function name:
fn identity<T>(x: T) -> T:
x
With trait bounds:
fn print_it<T: Display>(x: T):
print(x)
With where clauses:
fn convert<T, U>(x: T) -> U where T: Into<U>:
x.into()
Effects
Functions that perform side effects declare them with !(...) after the return type:
fn read_file(path: String) -> String !(IO):
// ...
fn complex(x: i64) -> String !(IO + State):
// ...
See Effects & Handlers for the full effect system.
Multi-Clause Functions
Functions can pattern-match on their arguments using multiple clauses. The body contains (patterns): body clauses, similar to match:
fn fib(n: i64) -> i64:
(0): 0
(1): 1
(n): fib(n - 1) + fib(n - 2)
Each clause lists patterns for the arguments in parentheses.
Function Type Parameters
Functions can accept other functions as parameters using fn(Args) -> Ret type syntax:
fn apply(f: fn(i64) -> i64, x: i64) -> i64:
f(x)
Visibility and Attributes
Functions are public by default. Use pvt for private:
pvt fn helper() -> i64:
42
Attributes precede the function:
#[inline]
fn fast(x: i64) -> i64:
x * 2
Everything Combined
#[some_attr]
pvt fn kitchen_sink<T, U: Default>(x: T, y: U) -> Result<T, U> !(IO + State) where T: Display + Clone:
// ...
Lambdas
Anonymous functions use pipe syntax:
let f = |x| x + 1
let add = |x, y| x + y
let constant = || 42
Lambdas are commonly used with higher-order functions:
items.map(|x| x * 2)
items.filter(|x| x > 0)
items.fold(0, |acc, x| acc + x)
Calling Functions
Standard call syntax:
add(5, 3)
f(g(x))
f(x + y, y * 2)
Method calls on values:
x.len()
x.concat(y)
x.trim().len() // chaining
Path-qualified calls:
Foo::new()
std::io::File::open("test.txt")