machdocs
Home GitHub

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;
    }
}
Restriction

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 - $if and $each inside function bodies
  • Expressions - function calls and generic instantiation
  • Types - the types parameters and returns are written in