ESC
Type to search...
S
Soli Docs

Functions

Function declarations, closures, higher-order functions, and default parameters in Soli.

Function Declaration

fn

Declares a function with optional parameters and return type.

// No parameters, no return
fn say_hello() {
    print("Hello!");
}

// With parameters
fn greet(name: String) {
    print("Hello, " + name + "!");
}

// With return value
fn add(a: Int, b: Int) -> Int {
    return a + b;
}

// Void function
fn log_message(msg: String) {
    print("[LOG] " + msg);
}

// Early return
fn absolute(x: Int) -> Int {
    if (x < 0) {
        return -x;
    }
    return x;
}

Recursive Functions

// Calculate factorial
fn factorial(n: Int) -> Int {
    if (n <= 1) {
        return 1;
    }
    return n * factorial(n - 1);
}

print(factorial(5));  // 120

// Calculate Fibonacci
fn fibonacci(n: Int) -> Int {
    if (n <= 1) {
        return n;
    }
    return fibonacci(n - 1) + fibonacci(n - 2);
}

print(fibonacci(10));  // 55

// Check if a number is prime
fn is_prime(n: Int) -> Bool {
    if (n < 2) {
        return false;
    }
    if (n == 2) {
        return true;
    }
    if (n % 2 == 0) {
        return false;
    }
    let i = 3;
    while (i * i <= n) {
        if (n % i == 0) {
            return false;
        }
        i = i + 2;
    }
    return true;
}

Higher-Order Functions

Functions can accept other functions as parameters:

// Function as parameter
fn apply(x: Int, f: (Int) -> Int) -> Int {
    return f(x);
}

fn double(x: Int) -> Int {
    return x * 2;
}

fn square(x: Int) -> Int {
    return x * x;
}

let result = apply(5, double);   // 10
let squared = apply(5, square);  // 25

// Passing anonymous functions
fn transform_array(arr: Int[], transformer: (Int) -> Int) -> Int[] {
    let result = [];
    for (item in arr) {
        push(result, transformer(item));
    }
    return result;
}

let numbers = [1, 2, 3, 4, 5];
let doubled = transform_array(numbers, fn(x) x * 2);  // [2, 4, 6, 8, 10]

Closures

Functions that capture variables from their enclosing scope:

// Counter using closure
fn make_counter() -> () -> Int {
    let count = 0;
    fn counter() -> Int {
        count = count + 1;
        return count;
    }
    return counter;
}

let counter1 = make_counter();
let counter2 = make_counter();

print(counter1());  // 1
print(counter1());  // 2
print(counter1());  // 3

print(counter2());  // 1
print(counter2());  // 2

// Closure capturing variables
fn make_greeter(greeting: String) -> (String) -> String {
    fn greet(name: String) -> String {
        return greeting + ", " + name + "!";
    }
    return greet;
}

let say_hello = make_greeter("Hello");
let say_hola = make_greeter("Hola");

print(say_hello("Alice"));  // "Hello, Alice!"
print(say_hola("Bob"));     // "Hola, Bob!"

Default Parameters

fn greet(name: String, greeting: String = "Hello") -> String {
    return greeting + ", " + name + "!";
}

print(greet("Alice"));              // "Hello, Alice!"
print(greet("Bob", "Hi"));          // "Hi, Bob!"
print(greet("Charlie", "Welcome")); // "Welcome, Charlie!"

// Optional parameters
fn create_user(name: String, email: String = null, role: String = "user") -> Hash {
    let user = {"name": name, "role": role};
    if (email != null) {
        user["email"] = email;
    }
    return user;
}

let user1 = create_user("Alice");
let user2 = create_user("Bob", "[email protected]");
let user3 = create_user("Charlie", "[email protected]", "admin");

Return Statement

return

Exits a function and optionally returns a value.

fn find_first_even(numbers: Int[]) -> Int {
    for (n in numbers) {
        if (n % 2 == 0) {
            return n;  // Early return
        }
    }
    return -1;  // Not found
}

let result = find_first_even([1, 3, 5, 4, 7]);  // 4