Functions

Functions are first-class citizens in Turbo. Define them, pass them around, and compose them with pipes.

Function Definitions

fn add(a: i64, b: i64) -> i64 {
    a + b
}

fn greet(name: str) {
    print("Hello, {name}!")
}

fn main() {
    print(add(2, 3))    // 5
    greet("world")       // Hello, world!
}

The last expression in a function body is its return value -- no return keyword needed (though you can use return for early returns).

Expression-Body Functions

When a function body is a single expression, the braces serve as the expression block:

fn double(x: i64) -> i64 { x * 2 }
fn is_positive(n: i64) -> bool { n > 0 }
fn identity<T>(x: T) -> T { x }

Higher-Order Functions

Functions can accept other functions as parameters:

fn apply(f: fn(i64) -> i64, x: i64) -> i64 {
    f(x)
}

fn main() {
    let double = |x: i64| -> i64 { x * 2 }
    print(apply(double, 21))    // 42
}

Closures

Closures are anonymous functions defined with the |args| body syntax:

fn main() {
    let double = |x: i64| -> i64 { x * 2 }
    print(double(5))        // 10

    let add = |a: i64, b: i64| -> i64 { a + b }
    print(add(3, 7))        // 10

    // Closures work with map, filter, reduce
    let nums = [1, 2, 3, 4, 5]
    let doubled = nums.map(|x: i64| -> i64 { x * 2 })
    let evens = nums.filter(|x: i64| -> bool { x % 2 == 0 })
}

The Pipe Operator

The |> pipe operator passes the left-hand value as the first argument to the right-hand function:

fn count_chars(text: str) -> i64 { len(text) }
fn count_words(text: str) -> i64 {
    let words = split(text, " ")
    len(words)
}

fn main() {
    let text = "Hello Turbo World"

    // Pipe operator for clean data flow
    let chars = text |> count_chars
    let words = text |> count_words
    print("Chars: {chars}, Words: {words}")

    // Chain string operations
    let sample = "  Hello, World!  "
    let cleaned = sample |> trim
    let upper = cleaned |> upper
    print(upper)    // "HELLO, WORLD!"
}

Recursion

Functions can call themselves recursively:

fn fib(n: i64) -> i64 {
    if n <= 1 {
        n
    } else {
        fib(n - 1) + fib(n - 2)
    }
}

fn factorial(n: i64) -> i64 {
    if n <= 1 { 1 }
    else { n * factorial(n - 1) }
}

fn main() {
    print(fib(10))          // 55
    print(factorial(10))    // 3628800
}