Functions
Learn how to define and use functions in Sounio
Functions
Functions in Sounio are first-class citizens with support for effects, generics, and more.
Basic Functions
fn add(a: i32, b: i32) -> i32 {
a + b
}
fn greet(name: String) {
print("Hello, " + name + "!")
}
Function Calls
let sum = add(3, 5) // 8
greet("World") // Hello, World!
Named Arguments
Sounio supports named arguments for clarity:
fn create_user(name: String, age: i32, email: String) -> User {
User { name, age, email }
}
let user = create_user(
name: "Alice",
age: 30,
email: "alice@example.com"
)
Default Arguments
fn connect(host: String, port: i32 = 8080, timeout: i32 = 30) {
// ...
}
connect("localhost") // port=8080, timeout=30
connect("localhost", port: 3000) // timeout=30
Effects Declaration
Functions that perform side effects must declare them:
fn read_file(path: String) -> String with IO {
// IO operations here
}
fn update_counter(c: &!Counter) with Mut {
c.value = c.value + 1
}
fn allocate_buffer(size: usize) -> Buffer with Alloc {
Buffer::new(size)
}
Multiple effects can be combined:
fn process_data(path: String) -> Result<Data> with IO, Alloc {
let content = read_file(path)
parse_and_allocate(content)
}
Generic Functions
fn identity<T>(x: T) -> T {
x
}
fn swap<T, U>(pair: (T, U)) -> (U, T) {
(pair.1, pair.0)
}
Closures
Anonymous functions (closures) capture their environment:
let multiplier = 3
let triple = |x| x * multiplier
let result = triple(5) // 15
With type annotations:
let add: fn(i32, i32) -> i32 = |a, b| a + b
Higher-Order Functions
Functions can take and return functions:
fn apply_twice<T>(f: fn(T) -> T, x: T) -> T {
f(f(x))
}
let double = |x: i32| x * 2
let result = apply_twice(double, 5) // 20
Methods
Functions can be defined on types:
struct Point {
x: f64,
y: f64,
}
impl Point {
fn new(x: f64, y: f64) -> Point {
Point { x, y }
}
fn distance(&self, other: &Point) -> f64 {
let dx = self.x - other.x
let dy = self.y - other.y
(dx * dx + dy * dy).sqrt()
}
}