Skip to content

Arrays

Zeus provides dynamic arrays that can grow and shrink at runtime.

Creating Arrays

The idiomatic way to create an array is an array literal — a comma-separated list of values in square brackets:

let numbers = [10, 20, 30]; // inferred: u8[] (each value fits u8)
let scores: i32[] = [95, 87, 100]; // annotate to pin a wider element type
let mixed = [1, 2.5]; // inferred: f64[] (widened to a common type)

The element type is inferred the same way as scalar literals: the smallest type that fits every element, widening across mixed numeric types. Add a type annotation when you want a specific width or signedness.

An empty literal has no elements to infer from, so it takes its type from a declaration annotation (or, when nested, from its sibling rows):

let todo: string[] = []; // empty — element type from the annotation
let rows = [[1], [2], []]; // the empty row is typed u8[] from its siblings

You can also construct arrays explicitly with new. Passing a size fills that many default-valued elements (the array’s length becomes that size):

let empty = new i32[]; // empty array (length 0)
let zeros = new i32[100]; // 100 zero-filled elements (length 100)

Basic Operations

let arr: i32[] = [10, 20, 30];
// Add an element
arr.push(40); // arr = [10, 20, 30, 40]
// Access elements (bracket notation or .get())
let first = arr[0]; // 10
let second = arr.get(1); // 20
// Modify elements (bracket notation or .set())
arr[0] = 100;
arr.set(1, 200); // arr = [100, 200, 30, 40]
// Remove last element
let last = arr.pop(); // Returns 40, arr = [100, 200, 30]
// Check length
let len = arr.length; // 3

Method Reference

Mutating Methods

MethodDescription
push(value)Add element to end
pop()Remove and return last element
set(index, value)Set element at index
fill(value)Fill all elements with value
clear()Remove all elements
copy(source)Copy elements from another array

Non-Mutating Methods

These return new arrays without modifying the original:

MethodDescription
concat(other)Combine two arrays
slice(start, end)Extract sub-array (end exclusive)
reverse()Reverse element order

Search Methods

MethodDescription
indexOf(value)First index of value, or -1
lastIndexOf(value)Last index of value, or -1
includes(value)Returns true if value exists
find(value)Returns element or default value
findIndex(value)Same as indexOf
isEmpty()Returns true if length is 0

Non-Mutating Operations

let arr = [1, 2, 3];
// concat - combine arrays
let other = [4, 5];
let combined = arr.concat(other); // [1, 2, 3, 4, 5]
// arr is still [1, 2, 3]
// slice - extract portion (start inclusive, end exclusive)
let middle = combined.slice(1, 4); // [2, 3, 4]
// reverse - reverse order
let reversed = arr.reverse(); // [3, 2, 1]
// arr is still [1, 2, 3]
// Chain operations
let result = arr.reverse().slice(0, 2); // [3, 2]

Searching

let arr: i32[] = [10, 20, 30, 20];
arr.indexOf(20); // 1 (first occurrence)
arr.lastIndexOf(20); // 3 (last occurrence)
arr.indexOf(999); // -1 (not found)
arr.includes(20); // true
arr.includes(999); // false
arr.isEmpty(); // false

Multi-Dimensional Arrays

Nested literals build multi-dimensional arrays directly:

// 2D
let matrix = [[1, 2], [3, 4]];
let value = matrix[0][1]; // 2
// 3D
let cube = [[[42]]];
let v = cube[0][0][0]; // 42
// Rows can be jagged, and an empty row is still typed from its siblings
let jagged = [[1, 2, 3], [4], []];

When the shape is only known at runtime, build the rows with new and push instead — see the Matrix Class example below.

Object Arrays

class Point {
public x: i32;
public y: i32;
constructor(x: i32, y: i32) {
this.x = x;
this.y = y;
}
}
// Build the array directly with a literal
let points = [new Point(1, 2), new Point(3, 4)];
let p = points[0];
let sum = p.x + p.y; // 3
// ...or incrementally with push
let more = new Point[];
more.push(new Point(5, 6));

Practical Examples

Sum Elements

function sumArray(arr: i32[]): i32 {
let sum = 0;
for (let i: i32 = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}

Remove Element at Index

function removeAt(arr: i32[], index: i32): i32[] {
let before: i32[] = arr.slice(0, index);
let after: i32[] = arr.slice(index + 1, arr.length);
return before.concat(after);
}

Matrix Class

class Matrix {
public data: i32[][];
constructor(rows: i32, cols: i32) {
this.data = new i32[][];
for (let i: i32 = 0; i < rows; i++) {
this.data.push(new i32[cols]);
}
}
public get(row: i32, col: i32): i32 {
return this.data[row][col];
}
public set(row: i32, col: i32, value: i32) {
this.data[row][col] = value;
}
}

Bounds Checking

Zeus performs automatic bounds checking when reading from arrays. Accessing an index outside the valid range throws an IndexOutOfBoundsException:

let arr = [10, 20];
let safe = arr[0]; // 10 - valid
let also_safe = arr[1]; // 20 - valid
let oob = arr[5]; // Throws IndexOutOfBoundsException!

Handling Bounds Errors

You can catch bounds errors using try-catch:

function safeGet(arr: i32[], index: i32): i32 {
try {
return arr[index];
} catch (e: Error) {
console.log("Index out of bounds: " + e.message);
return -1; // Return default value
}
}

Safe Access Pattern

Check length before accessing:

function getOrDefault(arr: i32[], index: i32, defaultValue: i32): i32 {
if (index < 0) {
return defaultValue;
}
if (index >= arr.length) {
return defaultValue;
}
return arr[index];
}