Array — array
Overview
Standard contiguous arrays with compile-time sizing.
Declaration
int32[5]:numbers;
numbers[0] = 10i32;
numbers[1] = 20i32;
numbers[2] = 30i32;
numbers[3] = 40i32;
numbers[4] = 50i32;
Access
int32:first = numbers[0]; // zero-indexed
int32:last = numbers[4];
if (numbers[2] != 30i32) {
// handle error
}
Slicing (v0.35.1)
Slice syntax uses a half-open range [lo, hi) — element lo is included,
element hi is excluded:
int64[5]:nums = [10, 20, 30, 40, 50];
int64[]:view = nums[1..3]; // elements at index 1, 2 — [20, 30]
int64[]:head = nums[0..2]; // first two elements — [10, 20]
int64[]:tail = nums[3..5]; // last two elements — [40, 50]
Slice bounds are checked at runtime; an out-of-bounds slice (lo < 0,
hi > len, or hi < lo) routes through the failsafe with error code 45.
A slice is a view into the original array's storage — reads and writes
alias the source; no copy is made.
Multi-Dimensional Arrays (v0.19.0)
Nitpick supports 2-D (and higher) arrays with nested bracket syntax:
int32[2][2]:sq = [[1, 2], [3, 4]];
int32:top_right = sq[0][1]; // 2
int32[3][4]:tbl;
int32:r = 1;
int32:c = 3;
tbl[r][c] = 42;
int32:val = tbl[r][c]; // 42
The first bracket is the outer (row) dimension; the second is the inner
(column) dimension. Access uses arr[row][col] for 2-D arrays.
Deprecated (v0.35.2): The legacy comma form
arr[i, j]still parses but emitsARIA-MULTIDIM-COMMA-DEPRECATED. Usearr[i][j]instead. Hard rejection is planned for ≥ v0.40.x.
Array Iteration (v0.35.3)
for elem in arr { ... } iterates every element of a fixed-size array or a
dynamic slice view:
int32[4]:nums = [10, 20, 30, 40];
for n in nums {
// n is int32, visited in order: 10, 20, 30, 40
};
// Parenthesized form is also accepted:
for (n in nums) {
// same
};
Explicit type annotation on the iterator is checked against the element type:
int64[3]:big = [100, 200, 300];
for int64:v in big {
// v is int64 — annotation matches element type
};
// for int32:v in big { ... } — COMPILE ERROR: int32 ≠ int64
Slice views are also iterable:
int32[5]:arr = [1, 2, 3, 4, 5];
int32[]:view = arr[1..4]; // [2, 3, 4]
for x in view {
// x visits 2, 3, 4
};
## Dynamic-Index Borrows (v0.19.0)
Array elements can be borrowed with `$$i` (immutable) or `$$m` (mutable) using
a variable as the index. The borrow checker treats any variable-index borrow as
targeting the entire array (path `[*]`) since the slot is not known at
compile time:
```nitpick
int32[3]:arr = [10, 20, 30];
int32:i = 1;
$$i int32:elem = arr[i]; // immutable borrow — read only
// arr is locked for mutation while elem is live
$$m int32:slot = arr[i]; // mutable borrow — write-back on release
slot = 99;
// arr[1] is now 99 after slot goes out of scope
Conflict rules:
- Two
$$mborrows to the same array via any variable index are rejected (both map to[*]— conservatively non-disjoint). - A literal-index borrow and a variable-index borrow on the same array are
rejected (ARIA-023 —
[k]and[*]cannot be proven disjoint). - Borrows on different arrays (even within the same struct) are fine.
// COMPILE ERROR — both borrow the same array's [*] path
$$m int32:a = arr[i];
$$m int32:b = arr[j]; // ARIA-023
// COMPILE ERROR — literal arr[0] conflicts with dynamic arr[i]
$$m int32:lit = arr[0];
$$m int32:dyn = arr[i]; // ARIA-023
Arrays-in-Structs Borrow Interaction (v0.19.0)
When a struct contains an array field, split borrows work across disjoint paths — a scalar field and an array element are distinct paths:
struct:Pair = {
int32:a;
int32[4]:buf;
};
Pair:p;
p.a = 10;
p.buf[1] = 2;
$$m int32:ra = p.a; // borrows path p.a
$$m int32:rb = p.buf[1]; // borrows path p.buf[1] — disjoint from p.a
ra = 3;
rb = 5;
// p.a == 3, p.buf[1] == 5 after both borrows release
Related
- types/vec.md — fixed-size vector types
- collections/astack.md — user stack (LIFO)
- collections/ahash.md — hash tables
- memory_model/borrow.md — borrow semantics
- control_flow/for.md — range-based and array-based for loops