Array types are for indexed collections of values that have the same type. There are many variations of built-in array types, distinguished by how they are declared:

imm staticarray [10] f32      // Static array (C-style)
imm arrref      &gc [] f32    // Array reference  
imm slice       &[] f32       // Array slice (borrowed array reference)
imm vecarray    [u32] f32     // Vector variable-sized array struct
imm maparray    [Text] f32    // Map: variable-sized associated array struct

Generally, the presence of square brackets in a declaration signals that you are working with some kind of indexed collection. Similarly, square brackets are used to access one or more elements of an indexed collection. Square brackets are also used to define an array literal.

Array type primitives

Let's start with the core language features that make support for array types possible: static arrays, array references, and use of pointers as arrays.

Static arrays

The size of a static array is fixed and declared using an unsigned integer literal inside square brackets:

mut text [4] u32

An array literal creates a static array:

mut list = [1f, 4f, 5f]   // [3] f32

An element within a static array is accessed using square brackets:

c_array[3] = c_array[2]

Array indexing is automatically bounds-checked by its known size.

Elements may be accessed using ranges as well:

    mut clk = "Abc"
    clk[0..1] = "Ti"          // clk is now "Tic"

Array References

Arrays created while the program is running are represented using array references. An array reference (unlike a regular reference) is a 2-value tuple containing:

An array reference is returned from an array allocation. This example allocates an array containing four floating point numbers:

imm n = 4
imm newarr = &gc [n] 0.   // newarr's type:  &gc [] f32

Array references may index elements in the same way as for static arrays. A run-time check is made to ensure the index is less than the size known to the array reference.

Since an array reference is a tuple, its parts can be retrieved within a trust block.

mut ptr, size = arrref

Slices

A slice is a borrowed array reference. A slice is created from an array or another slice using a range within square brackets.

imm x = &"Abc"[1..3]  // x is a slice pointing to "bc"
imm y = &"Abc"[..]    // y is a slice pointing to "Abc" (0 and end assumed)

A slice is always an alias; a fixed-size view into an array it was created from and cannot outlive or re-structure. Since slices are always borrowed references, they must conform to lifetime rules. Because slices use interior references, they cannot be created from an array that has the shared, mutable permission 'mut', as this could lead to potential memory safety problems.

Note: If a static array is passed as a parameter, it is automatically converted into a slice.

Pointers as arrays

Any pointer can be treated as if it were a pointer into an array, simply by indexing it within a trust block:

p[3]    // Equivalent to *(p+3)

No boundary checking is performed when indexing a pointer. This can be a useful performance boost if the index is already known to be valid.

Struct-based arrays

Structs are useful for creating a variable-sized array type. Use of a struct makes it possible to offer a useful range of methods and then wrap its implementation as private properties.

Square brackets may be used to index into a struct once the '[]' method is implemented:

struct VarArray
    _array &gc [] f32

    fn init(size usize)
        _array = &gc [size] f32

    fn `[]`(index usize) f32 trust
        if index < _size       // Should do bounds check
            _array[index]
        else
            0f                 // or panic

This struct acts like an array simply by responding to the [] method:

mut var VarArray
var[3] = var[2]

A slice may be obtained from a struct in the same way as from a fixed-size array, again after implementing the '&[]' method:

&vararray[..]

This invokes the &[] method with two arguments. That method returns a slice. For example:

    fn `&[]`(from usize, to usize) &[] f32 trust
        // .. boundary checking before this
        &_array[from .. to]

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.

_