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