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()
    }
}

What’s Next?