Functions
Functions are the primary unit of code organization in Vexel. They are declared at the top level of a file and can call each other freely, including recursively.
Basic Declaration
A function is declared with fn, the function name, a parameter list in parentheses, an optional return type after ->, and a colon to open the body.
# No parameters, no return value
fn greet():
print("Hello!")
# Parameters and return type
fn add(a: int, b: int) -> int:
return a + b
fn main():
greet()
let result: int = add(3, 4)
print(result) # 7 Return Values
Use return to exit a function and optionally pass back a value. If the function declares a return type, every code path must return a value of that type.
Functions without a return type annotation implicitly return nothing (void). A bare return can be used to exit early.
fn absolute(x: int) -> int:
if x < 0:
return -x
return x
# Early return — void function
fn check(n: int):
if n < 0:
print("negative")
return
print("non-negative") Default Parameters
Parameters can have default values. If the caller omits the argument, the default is used. Default parameters must come after non-default parameters.
fn power(base: int, exp: int = 2) -> int:
let result: int = 1
for i in 0..exp:
result = result * base
return result
fn main():
print(power(3)) # 9 (exp defaults to 2)
print(power(2, 10)) # 1024 Variadic Parameters
A function can accept a variable number of arguments using the ...name: T[] syntax. The variadic parameter must be the last parameter and collects all remaining arguments into an array.
fn sum(...nums: int[]) -> int:
let total: int = 0
for n in nums:
total += n
return total
fn main():
print(sum(1, 2, 3)) # 6
print(sum(10, 20, 30, 40)) # 100 Recursion
Functions can call themselves. Vexel has no recursion depth limit imposed by the language — the limit is the native call stack size.
fn fib(n: int) -> int:
if n <= 1:
return n
return fib(n - 1) + fib(n - 2) Lambda Expressions
Anonymous functions (lambdas) can be created inline and assigned to variables. They use the same fn syntax but without a name.
let double = fn(x: int) -> int:
return x * 2
print(double(5)) # 10 Generic Functions
Functions can be parameterized with type parameters using square bracket syntax. The type parameters are substituted at call sites.
fn identity[T](value: T) -> T:
return value
fn main():
print(identity[int](42)) # 42
print(identity[str]("hello")) # hello