Arrays are a family of types used to package together multiple, indexable values that are all of the same type.

The basic idea is that the internal behavior of square brackets for indexing changes based on type, but appears semantically equivalent to the programmer. If it is declared as a fixed-size array, bounded-pointer, or bounded-reference, the behavior is hard coded into the compiler. For all other types (particularly structs), the square brackets invoke the type's overloaded '[]' method for both get and set operations.

There are many variations of built-in array types, distinguished by how they are declared:

Additional array structures can be defined using templates and/or structs that build off the latter three array capabilities.

Vec: Variable-size arrays

Vec is the language standard template for a resizeable array. For ease-of-use, the language supports sugar for its use:

vec_array [u32] i32   // Equivalent to Vec[i32, u32]

The dimension must be an unsigned integer.

Map: Variable-size associated arrays

Map is the language standard template for a resizeable dictionary map. For ease-of-use, the language supports sugar for its use:

map_marray [Text] i32  // Equivalent to Map[i32, Text, usize]

The dimension here must be a type that supports the hash method.



Fixed-size arrays

Fixed-size arrays declare the size of the array using a constant, unsigned integer:

mut c_array [4] i32

Every attempt to index into such an array is automatically bounds-checked by its known size. (Note: This bounds check is not performed within a trust block.)

Bounded-pointer arrays

The declaration for a bounded-pointer array always occurs within a struct. For example:

struct VarArray
    size u32
    data *[size] i32  // <-- bounded-pointer array

TBD. Distinguish when to use bounded-pointers vs. bounded-references. Also, bounded-pointers can never be indexed outside a trust block which trips up bounds-checking!

The compiler recognizes this as a bounded-pointer array because the declared size of the array references the field that declares the array's size as an unsigned integer. Naming the companion field that specifies the array's size brings two advantages to the compiler:

Applying square brackets to the 'data' field is treated like a pointer that is bounds-checked. The bounds check happens automatically, but only if not within a trust block.

Note: Apply the square brackets to an instance of VarArray invokes the '[]' method defined for VarArray, which may or may not then invoke [] on the data field. Bounded-pointer arrays are a good mechanisms for implementing various variable-size array structures, and is what lies behind the Vec template (which adds a capacity field).

Bounded-reference arrays

This is similar to bounded-pointer arrays:

struct Slice
    offset usize
    size usize
    ref &[u32] i32

This is important for implementing slices via templates. In this case we have a borrowed (no allocator) reference with a known lifetime into some fixed or var size array. As shown, the Slice template takes advantage of this construct.