Skip to content

03 · Functions

Functions are declared with fn, take typed parameters, and return a typed value. A function with no explicit return type returns () (unit). Effects propagate automatically — if a function calls println!, the compiler infers !io and requires the caller to also carry !io.

functions.cssl
// Pure function — no effects. Safe to call from anywhere.
fn add(a: i32, b: i32) -> i32 {
a + b
}
// Returns the larger of two floats.
fn max_f32(a: f32, b: f32) -> f32 {
if a >= b { a } else { b }
}
// Prints a greeting — carries !io because of println!.
fn greet(name: str) !io {
println!("Hello, {}!", name);
}
fn main() !io {
let sum = add(2, 3);
println!("2 + 3 = {}", sum);
let m = max_f32(1.5, 2.7);
println!("max = {}", m);
greet("Sigil");
}
2 + 3 = 5
max = 2.7
Hello, Sigil!

add and max_f32 are provably pure — calling them from a !gpu shader or a @verify-annotated function is legal. greet is !io; calling it from a pure context is a compile error. The last expression in a block is the implicit return value — no return keyword required.


Next → 04 · Structs