Skip to content

Arrays & Slices

Array length is part of the type and must be known at compile time.

Int[3] values = [1, 2, 3];
// Length mismatch is an error.
// Int[5] bad = [1, 2, 3];

Heap arrays use an owning pointer:

Int[3]^ owner = new [1, 2, 3];
print(owner.length);

Use _ in the array length or infer the whole type:

_ a = [1, 2, 3];
Int[_] b = [1, 2, 3];
Int[3] c = [1, 2, 3];

Array types do not encode binding mutability. Put ! after the binding name to allow element writes and replacement of the complete array:

Int[_] values! = [1, 2, 3];
values[1] = 4;
values = [4, 5, 6];

Jiang does not need a separate multidimensional array form. Repeated array suffixes build nested arrays:

Int[2][3] matrix = [[1, 2], [3, 4], [5, 6]];
matrix[0]; // [1, 2]
matrix[0][1]; // 2

Read Int[2][3] as Int -> Int[2] -> Int[2][3].

Int?[2][3] nullable_items = [[1, null], [3, 4], [5, 6]];
Int?[2]?[3] nullable_rows = [[1, null], null, [5, 6]];

T[] is an unsized array type whose length is known at runtime. Bare T[] is not a normal by-value type. Use T[]& for a borrowed runtime-length view over contiguous storage. The borrowed slice does not own the storage.

Int[_] values = [1, 2, 3];
Int[]& view = values[..];
print(view.length);

Sentinel slices use T[:S]&. A string literal naturally has type UInt8[:0]&; use text.slice() or text$.as(UInt8[]&) when a non-literal sentinel slice must be viewed as a plain UInt8[]&:

UInt8[:0]& text = "hello";
UInt8[]& bytes = text.slice();

Indexing a slice can produce an element reference:

_ item_ref = view[1]$.ref();

T[]& is a borrowed view and does not own the underlying storage. Vector<T>.slice() returns such a borrowed view. T[]^ is the owned unsized array handle. Use Vector<T>.into_slice() when the vector should be consumed and its initialized items should become an owned T[]^; the original vector is moved and cannot be used afterward.

T* is the raw pointer form for contiguous elements without a length:

UInt8* data;
Int length;
UInt8 first = unsafe { data[0] };

Raw-pointer indexing is unsafe because the pointer carries no length. T* supports reads and T*! supports reads and writes. Use T[]& when Jiang code needs a borrowed length-bearing view; the old T[*] and T[*:S] types have been removed.