Conjure provides multiple ways to work with collections of values. Fixed-size arrays offer compile-time guarantees and zero overhead, while slices and lists provide dynamic sizing when you need flexibility.
Fixed-Size Arrays
Arrays have a size that’s known at compile time and cannot change, with the size being part of the type. The array size is specified in square brackets before the element type.
var numbers [5]i32 = {10, 20, 30, 40, 50}
var colors [3]string = {"red", "green", "blue"}Array Initialization
You can initialize arrays with explicit values using braces.
var primes = [5]i32{2, 3, 5, 7, 11}When the size can be inferred from the number of elements, you can omit it.
var primes = []i32{2, 3, 5, 7, 11} // size inferred as 5Initialize all elements to the same value using the array constructor.
var zeros = [100]i32{...0} // all 100 elements are 0
var ones = [50]f32{...1.0} // all 50 elements are 1.0Without explicit initialization, array elements are set to their zero values.
var buffer [1024]u8 // all bytes are 0Accessing Elements
Array elements are accessed using square brackets with zero-based indexing.
var numbers = [5]i32{10, 20, 30, 40, 50}
var first = numbers[0] // 10
var third = numbers[2] // 30
var last = numbers[4] // 50Bounds checking is performed in debug builds. In release builds, bounds checking is omitted for performance, so out-of-bounds access is undefined behavior.
Modifying Elements
Change array elements by assigning to an index.
var scores = [3]i32{85, 90, 78}
scores[1] = 95
scores[2] = 82Multi-Dimensional Arrays
Arrays can be nested to create multi-dimensional structures.
var matrix = [3,3]i32{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
}
var center = matrix[1,1] // 5
matrix[0,2] = 99You can also write this with repeated brackets.
var matrix [3][3]i32
var value = matrix[1][1]Both syntaxes are equivalent, though the comma notation is more concise.
Array Length
Get the length of an array using the .len property.
var numbers = [5]i32{1, 2, 3, 4, 5}
var length = numbers.len // 5Since array sizes are compile-time constants, .len is also a compile-time constant.
Iterating Over Arrays
Use for-in loops to iterate over array elements.
var names = [3]string{"Alice", "Bob", "Charlie"}
for name in names {
c.printf("%s\n", name)
}Access both index and value using the comma syntax.
for i, name in names {
c.printf("%d: %s\n", i, name)
}Slices (and Lists)
Slices are views into arrays or other slices. They have a pointer to the underlying data, a length, and a capacity. Slices are written as []T where T is the element type and, unlike languages like Go, cannot be sized larger than the underlying array.
var numbers = [10]i32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
var slice []i32 = numbers[2..5] // slice of elements 2, 3, 4, 5The reason a slice cannot be sized larger than the underlying array is that they retain a pointer to the original array, allowing modifications to the slice to affect the underlying array. However, slices can be promoted to lists which are dynamically sized arrays that manage their own memory.
To create a list from a slice, you can cast the slice with the target type being List[T] where T is the element type. Lists are part of the standard library’s list module.
var slice []i32
var list = List[i32](slice) // creates a List[i32] copy of the sliceYou can also create lists directly arrays by casting an array to a list.
var arr = [5]i32{1, 2, 3, 4, 5}
var list = List[i32](arr) // creates a List[i32] copy of the arrayCreating Slices
Extract a slice from an array using range syntax.
var arr = [10]i32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
var slice1 = arr[2..5] // elements at indices 2, 3, 4, 5
var slice2 = arr[0...3] // elements at indices 0, 1, 2, 3
var slice3 = arr[5..] // from index 5 to end
var slice4 = arr[..5] // from start to index 5
var slice5 = arr[..] // entire array as sliceSlices reference the original array’s memory. Modifying a slice modifies the underlying array.
var numbers = [5]i32{1, 2, 3, 4, 5}
var slice = numbers[1..3]
slice[0] = 99
c.printf("%d\n", numbers[1]) // prints 99Slice Properties
Slices have both length and capacity. Length is the number of elements in the slice and capacity reflects the maximum size of the underlying array from the starting index of the slice.
var numbers = [10]i32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
var slice = numbers[2..5]
var length = slice.len // 4 (indices 2, 3, 4, 5)
var capacity = slice.cap // 8 (can grow to index 9)String Arrays
Arrays and lists of strings work the same as any other type.
var names = [3]string{"Alice", "Bob", "Charlie"}Memory Layout
Fixed arrays are allocated inline, either on the stack for local variables or embedded in structs.
struct Point {
coords [3]f32 // embedded in the struct
}Slices are lightweight views containing a pointer, length, and capacity. They don’t own their data.
Performance Considerations
Fixed arrays have zero overhead and optimal cache locality. Use them when the size is known at compile time.
Slices add minimal overhead for the length and capacity tracking. They’re ideal for passing array subsets to functions.
Passing to Functions
Arrays are passed by value, meaning they’re copied. For large arrays, use slices or pointers to avoid expensive copies.
// Copies the entire array
func processArray(arr [1000]i32) {
// ...
}
// Passes a slice (just pointer + length + capacity)
func processSlice(slice []i32) {
// ...
}Slices and lists are already lightweight references, so passing them is cheap.
Array Literals in Expressions
Array literals can be used anywhere an array value is expected.
var max = findMax([5]i32{3, 7, 2, 9, 1})
func findMax(arr [5]i32) i32 {
var max = arr[0]
for value in arr {
if value > max {
max = value
}
}
return max
}Nested Collections
You can nest arrays, slices, and lists in any combination.
var grid = [10][10]i32{}
var jaggedArray = List[[]i32]{}
var matrix = List[List[f32]]{}This flexibility lets you choose the right collection type for each level of nesting.