Functions

Defining, calling, and advanced function features.

Basic Function Definition

Functions are declared with func, parameters with types, and a return type:

func greet(str $name) str {
    return "Hello, " . $name . "!";
}

func add(int $a, int $b) int {
    return $a + $b;
}

func print_message(str $msg) void {
    say($msg);
    # No return needed for void functions
}

Calling Functions

my str $greeting = greet("World");
my int $sum = add(10, 20);
print_message("Hello!");

Parameter Types

Scalar Parameters

func process(int $n, str $label, num $factor) void {
    say($label . ": " . ($n * $factor));
}

Array Parameters

func sum_array(array @numbers) int {
    my int $total = 0;
    foreach my int $n (@numbers) {
        $total += $n;
    }
    return $total;
}

my array @nums = [1, 2, 3, 4, 5];
say(sum_array(@nums));  # 15

Hash Parameters

func print_config(hash %config) void {
    my array @keys = keys(%config);
    foreach my str $key (@keys) {
        say($key . ": " . $config{$key});
    }
}

Return Types

Return Type Description
voidNo return value
intReturns integer
numReturns floating-point
strReturns string
arrayReturns array
hashReturns hash
scalarReturns any value

Anonymous Functions (Closures)

Strada supports first-class anonymous functions that capture variables from their enclosing scope:

# Create an anonymous function
my scalar $double = func (int $n) {
    return $n * 2;
};

# Call with arrow syntax
say($double->(5));  # 10
say($double->(21)); # 42

Capturing Variables

Closures capture variables by reference:

func make_counter() scalar {
    my int $count = 0;

    return func () {
        $count++;
        return $count;
    };
}

my scalar $counter = make_counter();
say($counter->());  # 1
say($counter->());  # 2
say($counter->());  # 3

Higher-Order Functions

func apply(scalar $fn, int $value) scalar {
    return $fn->($value);
}

my scalar $square = func (int $n) { return $n * $n; };
my scalar $negate = func (int $n) { return -$n; };

say(apply($square, 5));  # 25
say(apply($negate, 5)); # -5

Optional Parameters

Parameters with default values are optional:

func greet(str $name, str $greeting = "Hello") str {
    return $greeting . ", " . $name . "!";
}

say(greet("Alice"));             # Hello, Alice!
say(greet("Bob", "Hi"));        # Hi, Bob!

Variable Arguments

Accept any number of arguments with @args:

func sum(array @numbers) int {
    my int $total = 0;
    foreach my int $n (@numbers) {
        $total += $n;
    }
    return $total;
}

say(sum(1, 2, 3));         # 6
say(sum(1, 2, 3, 4, 5)); # 15

Function References

Get a reference to a named function with \&funcname:

func double(int $n) int {
    return $n * 2;
}

my scalar $ref = \&double;
say($ref->(10));  # 20

Recursion

func factorial(int $n) int {
    if ($n <= 1) {
        return 1;
    }
    return $n * factorial($n - 1);
}

say(factorial(5));  # 120

func fibonacci(int $n) int {
    if ($n <= 1) {
        return $n;
    }
    return fibonacci($n - 1) + fibonacci($n - 2);
}

External Functions (C Interop)

Declare external C functions with extern:

# Declare external C function
extern func my_c_function(int $arg) int;

# Call it like any other function
my int $result = my_c_function(42);

Signal Handlers

Functions can be used as signal handlers:

func handle_sigint() void {
    say("Caught SIGINT!");
    sys::exit(0);
}

# Register the handler
sys::signal("INT", \&handle_sigint);

# Or ignore signals
sys::signal("PIPE", "IGNORE");

Best Practices

Function Design Tips
  • Use specific types when possible, scalar only when needed
  • Keep functions small and focused on one task
  • Use descriptive names: calculate_total not calc
  • Document complex functions with comments