Generics & slices

Monomorphized generics and fat-pointer slices, with sub-slicing and for-in iteration.

Generics

Generics are monomorphized โ€” a type parameter is substituted everywhere it appears, including inside compound spellings like T[] and T*.

fun id<T>(T value) -> T {
    return value
}

struct Box<T> {
    T value
}

Generic functions and classes work across module boundaries: an exported template (e.g. std::vec.Vector<T>) is instantiated in the importing module.

Slices

A slice T[] is a fat pointer: a 16-byte value holding a pointer and a length. Unlike a fixed array (T[N], stored inline) or a raw pointer (T*, no length), a slice knows how many elements it spans.

fun sum(i32[] xs) -> i32 {
    i32 total = 0
    for x in xs {
        total = total + x
    }
    return total
}

fun demo() -> i32 {
    i32[3] arr                  // fixed array (inline storage)
    arr[0] = 10
    arr[1] = 20
    arr[2] = 12
    i32[] s = arr               // slice over the array (ptr + len 3)
    i32[] lit = [1, 2, 3]       // slice over an array literal
    return sum(s)
}

Members are .ptr (type T*) and .len (type i64). Indexing is bounds-unchecked by default; compile with --bounds-check to trap on out-of-range access.

Sub-slicing

A half-open range [start..end) produces a new slice over the same storage (no copy); either bound may be omitted:

i32[] s = [10, 20, 30, 40, 50]
i32[] a = s[1..4]   // {20, 30, 40}
i32[] b = s[2..]    // {30, 40, 50}
i32[] c = s[..2]    // {10, 20}
i32[] d = s[..]     // whole slice

for-in

for iterates a half-open integer range or the elements of a slice, fixed array, or text:

for i in 0..xs.len { /* i is the counter */ }
for x in xs         { /* x is a copy of each element */ }
for b in "hi"       { /* iterate bytes (u8) */ }

Next: The insty compiler.