Functions
A function takes typed arguments, optionally returns a typed value, and runs a body of statements. Beyond the plain form, fun also carries generic type parameters, compile-time value parameters, and a trailing variadic pack.
Declaring a function
Every function starts with fun, a name, a parenthesized parameter list, an optional return type, and a brace-delimited body. The return type sits between the parameter list and the body; omit it for a function that returns nothing.
fun NAME(args) RET { ... } # function with return type
fun NAME(args) { ... } # no return type
fun NAME[T](args) RET { ... } # generic over type parameters
fun NAME($p: T, args) RET { ... } # comptime value parameter
fun NAME(fixed, va: ...) RET { ... } # variadic pack parameter
Parameters are written name: Type. A value is returned with ret.
pub fun add(a: i64, b: i64) i64 {
ret a + b;
}
pub fun bump() { # no return value
counter = counter + 1;
}
Generic type parameters
Generic functions take type parameters in brackets, [T]. There are no constraints: any type may be substituted. The compiler monomorphizes a separate instance per unique type instantiation.
pub fun identity[T](value: T) T {
ret value;
}
pub fun make_pair[T, U](a: T, b: U) Pair[T, U] {
var p: Pair[T, U];
p.left = a;
p.right = b;
ret p;
}
Call sites supply the types explicitly in brackets:
val x: i64 = identity[i64](42);
val p: Pair[i64, u8] = make_pair[i64, u8](1, 2u8);
Comptime value parameters
A parameter marked $name: T must be supplied with a value the compiler can resolve at compile time. The body can branch on it with $if, producing different code per call-site instantiation.
pub fun pick_op($mode: Mode, a: i64, b: i64) i64 {
$if (mode == MODE_FAST) {
ret a + b;
}
$or (mode == MODE_SAFE) {
# extra logic here
ret a + b;
}
}
Comptime value parameters apply to function parameters only - not record fields, and not other contexts.
Variadic packs
A trailing named pack parameter, va: ..., accepts a variable number of trailing arguments. Any number of leading fixed parameters may precede it. The compiler monomorphizes the function once per distinct call-site type-list; the pack is consumed by $each a in va at compile time. There is no runtime va_list.
pub fun sum(va: ...) i64 {
var t: i64 = 0;
$each a in va {
t = t + a;
}
ret t;
}
# leading fixed params are allowed before the pack
pub fun bias(base: i64, va: ...) i64 {
var t: i64 = base;
$each a in va { t = t + a; }
ret t;
}
va.len folds to the element count, and g(va...) forwards the whole pack to another pack-tailed callee. See the variadic packs reference for the full rules.
See also
- Variadic packs - the full pack parameter reference
- Control flow -
$ifand$eachinside function bodies - Expressions - function calls and generic instantiation
- Types - the types parameters and returns are written in