Arrays
Arrays in Vex are fixed-size, statically-typed collections. Their size is known at compile time and is part of the type signature: [T; N] where T is the element type and N is the element count.
Declaration and Initialization
// Explicit type + literal
let arr: [i32; 4] = [1, 2, 3, 4]
// Inferred type
let names = ["Alice", "Bob", "Charlie"]
// Repeated value: creates [0, 0, 0, 0, 0]
let zeros: [i32; 5] = [0; 5]
// Using array literal with type suffix on first element
let floats = [1.0f32, 2.0, 3.0]Type Signature
The array type [T; N] carries the element type AND the length:
fn sum4(values: [i32; 4]): i32 {
let! total = 0
for v in values {
total += v
}
return total
}
// Caller passes exactly 4 elements
let result = sum4([10, 20, 30, 40])Element Access
let arr = [10, 20, 30, 40]
// Index access (zero-based)
let first = arr[0] // 10
let last = arr[3] // 40
// Mutable access requires let!
let! mut_arr = [1, 2, 3]
mut_arr[1] = 99Array Operations
Length
let arr = [5, 10, 15]
let len = arr.len() // 3 (compile-time known)Iteration
let values = [100, 200, 300]
// By value (Copy types only)
for v in values {
$println(v)
}
// Collection functions work naturally
let doubled = values.map(fn(x) => x * 2)
// Reduction
let sum = <+ values // 600Slicing and Span Conversion
Arrays automatically coerce to Span<T> for functions that accept borrowed views:
fn printSpan(s: Span<i32>) { ... }
let arr = [1, 2, 3, 4, 5]
printSpan(arr) // automatically coerces to Span<i32>Array to Tensor Auto-Promotion
When you perform arithmetic on arrays, Vex automatically promotes them to Tensor<T, N> for SIMD vectorization. This is one of Vex's killer features -- no manual SIMD intrinsics required.
let a = [1.0, 2.0, 3.0, 4.0]
let b = [5.0, 6.0, 7.0, 8.0]
// Element-wise addition compiles to a single SIMD instruction
let c = a + b // Tensor<f64, 4> = [6.0, 8.0, 10.0, 12.0]
// Scalar broadcast: scalar is splatted across all lanes
let d = a + 10.0 // [11.0, 12.0, 13.0, 14.0]
// Comparison produces Mask<N>
let eq = a == b // Mask<4> = [false, false, false, false]Inline SIMD Threshold
Arrays of 64 bytes or fewer (e.g., up to 8 f64 or 16 f32) fit in SIMD registers and compile to single vector instructions. Larger arrays use loop-based vectorization with SIMD chunks.
// Fits in register (32 bytes) -> single vaddps
let small = [1.0f32, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]
// Exceeds 64 bytes -> loop vectorization with 256-bit chunks
let big: [f32; 64] = [0.0; 64]Multidimensional Arrays
Vex supports nested arrays for multidimensional data:
// 3x3 matrix as array of arrays
let matrix: [[i32; 3]; 3] = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
let center = matrix[1][1] // 5Pattern Matching on Arrays
Arrays support destructuring in match and let patterns:
let triple = [10, 20, 30]
// Destructure in match
match triple {
[a, b, c] => a + b + c,
_ => 0,
}
// Destructure in let
let [first, second, third] = triple
// Rest patterns for partial binding
let [head, ..rest] = triple
// head = 10, rest is Span<i32> with [20, 30]
let [first, .., last] = triple
// first = 10, last = 30Copy vs Non-Copy Element Types
Arrays of Copy types (primitives, small structs marked Copy) are themselves Copy:
let a = [1, 2, 3] // [i32; 3] is Copy
let b = a // bitwise copy, a is still usableArrays of non-Copy types are moved on assignment:
let a = [Box.new(1), Box.new(2)] // [Box<i32>; 2] is NOT Copy
let b = a // move, a is no longer usableBest Practices
- Use arrays for small, fixed-size data where the length is known at compile time.
- Prefer
Vec<T>for dynamically-sized collections that grow at runtime. - Use
Span<T>as function parameter types to accept both arrays and Vec slices. - Let Vex auto-promote arrays to tensors for SIMD math -- never write manual SIMD intrinsics for array operations.
- Use
[value; N]syntax to initialize arrays with a repeated default value.
Related Pages
- Tuples -- heterogeneous fixed-size grouping
- Vec -- dynamic array with auto-growth
- SIMD Operations -- array auto-vectorization
- Pattern Matching -- destructuring arrays