Arrays

Arrays hold a fixed number of values of the same type. They’re stack-allocated, fast, and the compiler knows their size at compile time.

Declaring Arrays

Specify the type and size, then initialize with values in braces:

fn main() {
    var scores:i32[5] = {92, 87, 95, 78, 88}
    var names:str[3] = {"Alice", "Bob", "Charlie"}

    print("First score: {scores[0]}\n")
    print("First name: {names[0]}\n")
}

The syntax reads as: i32[5] means “5 values of type i32.”

Indexing

Arrays are zero-indexed — the first element is at position 0:

fn main() {
    var colors:str[4] = {"red", "green", "blue", "yellow"}

    print("Index 0: {colors[0]}\n")  // red
    print("Index 1: {colors[1]}\n")  // green
    print("Index 2: {colors[2]}\n")  // blue
    print("Index 3: {colors[3]}\n")  // yellow
}

Modifying Elements

Assign to a specific index:

fn main() {
    var nums:i32[4] = {10, 20, 30, 40}

    print("Before: {nums[1]}\n")  // 20
    nums[1] = 99
    print("After: {nums[1]}\n")   // 99
}

Iterating with For-Each

The cleanest way to process every element:

fn main() {
    var prices:f32[5] = {9.99, 24.50, 3.75, 15.00, 7.25}
    var total:f32 = 0.0

    for (var price in prices) {
        total += price
    }

    print("Total: {total}\n")
}

Iterating with For-Range

When you need the index:

fn main() {
    var items:str[4] = {"Sword", "Shield", "Potion", "Map"}

    for (i = 0:3) {
        print("Slot {i}: {items[i]}\n")
    }
}

Filtered Iteration

Use where to process only matching elements:

fn main() {
    var temps:i32[7] = {18, 25, 31, 22, 35, 28, 19}

    print("Hot days (above 30): ")
    for (var t in temps) where (t > 30) {
        print("{t}C ")
    }
    print("\n")
}

Practical Example: Finding Min and Max

fn main() {
    var data:i32[6] = {42, 17, 93, 5, 68, 31}
    var min = data[0]
    var max = data[0]

    for (var val in data) {
        if (val < min) {
            min = val
        }
        if (val > max) {
            max = val
        }
    }

    print("Min: {min}\n")  // 5
    print("Max: {max}\n")  // 93
}

Try it — Create an array and find the average value in the Playground.


Expert Corner

Stack-allocated, known size: Fixed arrays live on the stack. i32[1000] uses 4000 bytes of stack space — no heap allocation, no malloc, no free. The compiler knows the exact size, so iteration compiles to a simple counted loop in C.

Why i32[5] syntax? The type comes first, the count brackets follow. It reads naturally as “an array of 5 i32s.” This differs from C’s int arr[5] where the size is after the name. GX puts all type information together, making complex declarations more readable.

For-each under the hood: When you write for (var x in arr), the compiler generates a standard indexed loop in C: for (int i = 0; i < 5; i++) { int x = arr[i]; ... }. Zero abstraction cost — it’s exactly what you’d write by hand.

Bounds checking can be enabled for debug builds. In release mode, array access compiles to direct pointer arithmetic with no bounds check — maximum speed. Use var s = arr[i] knowing that out-of-bounds is undefined behavior in release, just like C.