Arrays
Arrays consist of the following:
- Arrays are mutable, ordered collections of values.
- Arrays may contain a value multiple times.
- Array literals start with an opening square bracket
[
and end with a closing square bracket]
.
_10// An empty array_10//_10[]_10_10// An array with integers_10//_10[1, 2, 3]
Array types
Arrays either have a fixed size or are variably sized (i.e., elements can be added and removed).
Fixed-size array types have the form [T; N]
, where T
is the element type and N
is the size of the array. N
must be statically known, meaning that it needs to be an integer literal. For example, a fixed-size array of 3 Int8
elements has the type [Int8; 3]
.
Variable-size array types have the form [T]
, where T
is the element type. For example, the type [Int16]
specifies a variable-size array of elements that have type Int16
.
All values in an array must have a type, which is a subtype of the array's element type (T
).
It is important to understand that arrays are value types and are only ever copied when used as an initial value for a constant or variable, when assigning to a variable, when used as function argument, or when returned from a function call.
_26let size = 2_26// Invalid: Array-size must be an integer literal_26let numbers: [Int; size] = []_26_26// Declare a fixed-sized array of integers_26// which always contains exactly two elements._26//_26let array: [Int8; 2] = [1, 2]_26_26// Declare a fixed-sized array of fixed-sized arrays of integers._26// The inner arrays always contain exactly three elements,_26// the outer array always contains two elements._26//_26let arrays: [[Int16; 3]; 2] = [_26 [1, 2, 3],_26 [4, 5, 6]_26]_26_26// Declare a variable length array of integers_26var variableLengthArray: [Int] = []_26_26// Mixing values with different types is possible_26// by declaring the expected array type_26// with the common supertype of all values._26//_26let mixedValues: [AnyStruct] = ["some string", 42]
Array types are covariant in their element types. For example, [Int]
is a subtype of [AnyStruct]
. This is safe because arrays are value types and not reference types.
Array indexing
To get the element of an array at a specific index, the following indexing syntax can be used: the array is followed by an opening square bracket [
, the indexing value, and ends with a closing square bracket ]
.
Indexes start at 0 for the first element in the array.
Accessing an element which is out of bounds results in a fatal error at run-time and aborts the program.
_14// Declare an array of integers._14let numbers = [42, 23]_14_14// Get the first number of the array._14//_14numbers[0] // is `42`_14_14// Get the second number of the array._14//_14numbers[1] // is `23`_14_14// Run-time error: Index 2 is out of bounds, the program aborts._14//_14numbers[2]
_10// Declare an array of arrays of integers, i.e. the type is `[[Int]]`._10let arrays = [[1, 2], [3, 4]]_10_10// Get the first number of the second array._10//_10arrays[1][0] // is `3`
To set an element of an array at a specific index, the indexing syntax can be used as well.
_12// Declare an array of integers._12let numbers = [42, 23]_12_12// Change the second number in the array._12//_12// NOTE: The declaration `numbers` is constant, which means that_12// the *name* is constant, not the *value* – the value, i.e. the array,_12// is mutable and can be changed._12//_12numbers[1] = 2_12_12// `numbers` is `[42, 2]`
Array fields and functions
Arrays have multiple built-in fields and functions that can be used to get information about and manipulate the contents of the array.
The field length
, and the functions concat
, and contains
are available for both variable-sized and fixed-sized or variable-sized arrays.
-
_10let length: Int
The number of elements in the array.
_10// Declare an array of integers._10let numbers = [42, 23, 31, 12]_10_10// Find the number of elements of the array._10let length = numbers.length_10_10// `length` is `4` -
_10access(all)_10view fun concat(_ array: T): T
Concatenates the parameter
array
to the end of the array the function is called on, but does not modify that array.Both arrays must be the same type
T
.This function creates a new array whose length is the sum of the length of the array the function is called on and the length of the array given as the parameter.
_12// Declare two arrays of integers._12let numbers = [42, 23, 31, 12]_12let moreNumbers = [11, 27]_12_12// Concatenate the array `moreNumbers` to the array `numbers`_12// and declare a new variable for the result._12//_12let allNumbers = numbers.concat(moreNumbers)_12_12// `allNumbers` is `[42, 23, 31, 12, 11, 27]`_12// `numbers` is still `[42, 23, 31, 12]`_12// `moreNumbers` is still `[11, 27]` -
_10access(all)_10view fun contains(_ element: T): Bool
Returns true if the given element of type
T
is in the array._15// Declare an array of integers._15let numbers = [42, 23, 31, 12]_15_15// Check if the array contains 11._15let containsEleven = numbers.contains(11)_15// `containsEleven` is `false`_15_15// Check if the array contains 12._15let containsTwelve = numbers.contains(12)_15// `containsTwelve` is `true`_15_15// Invalid: Check if the array contains the string "Kitty"._15// This results in a type error, as the array only contains integers._15//_15let containsKitty = numbers.contains("Kitty") -
_10access(all)_10view fun firstIndex(of: T): Int?
Returns the index of the first element matching the given object in the array, nil if no match. Available if
T
is not resource-kinded and equatable._10// Declare an array of integers._10let numbers = [42, 23, 31, 12]_10_10// Check if the array contains 31_10let index = numbers.firstIndex(of: 31)_10// `index` is 2_10_10// Check if the array contains 22_10let index = numbers.firstIndex(of: 22)_10// `index` is nil -
_10access(all)_10view fun slice(from: Int, upTo: Int): [T]
Returns an array slice of the elements in the given array from start index
from
up to, but not including, the end indexupTo
. This function creates a new array whose length isupTo - from
. It does not modify the original array. If either of the parameters are out of the bounds of the array, or the indices are invalid (from > upTo
), then the function will fail._11let example = [1, 2, 3, 4]_11_11// Create a new slice of part of the original array._11let slice = example.slice(from: 1, upTo: 3)_11// `slice` is now `[2, 3]`_11_11// Run-time error: Out of bounds index, the program aborts._11let outOfBounds = example.slice(from: 2, upTo: 10)_11_11// Run-time error: Invalid indices, the program aborts._11let invalidIndices = example.slice(from: 2, upTo: 1) -
_10access(all)_10view fun reverse(): [T]
Returns a new array with contents in the reversed order. Available if
T
is not resource-kinded._10let example = [1, 2, 3, 4]_10_10// Create a new array which is the reverse of the original array._10let reversedExample = example.reverse()_10// `reversedExample` is now `[4, 3, 2, 1]`_10access(all)_10view fun reverse(): [T; N]Returns a new fixed-sized array of same size with contents in the reversed order.
_10let fixedSizedExample: [String; 3] = ["ABC", "XYZ", "PQR"]_10_10// Create a new array which is the reverse of the original array._10let fixedArrayReversedExample = fixedSizedExample.reverse()_10// `fixedArrayReversedExample` is now `["PQR", "XYZ", "ABC"]` -
_10access(all)_10fun map(_ f: fun(T): U): [U]
Returns a new array whose elements are produced by applying the mapper function on each element of the original array. Available if
T
is not resource-kinded._18let example = [1, 2, 3]_18let trueForEven =_18fun (_ x: Int): Bool {_18return x % 2 == 0_18}_18_18let mappedExample: [Bool] = example.map(trueForEven)_18// `mappedExample` is `[False, True, False]`_18// `example` still remains as `[1, 2, 3]`_18_18// Invalid: Map using a function which accepts a different type._18// This results in a type error, as the array contains `Int` values while function accepts_18// `Int64`._18let functionAcceptingInt64 =_18fun (_ x: Int64): Bool {_18return x % 2 == 0_18}_18let invalidMapFunctionExample = example.map(functionAcceptingInt64)The
map
function is also available for fixed-sized arrays:_10access(all)_10fun map(_ f: fun(T): U): [U; N]Returns a new fixed-sized array whose elements are produced by applying the mapper function on each element of the original array. Available if
T
is not resource-kinded._18let fixedSizedExample: [String; 3] = ["ABC", "XYZYX", "PQR"]_18let lengthOfString =_18fun (_ x: String): Int {_18return x.length_18}_18_18let fixedArrayMappedExample = fixedSizedExample.map(lengthOfString)_18// `fixedArrayMappedExample` is now `[3, 5, 3]`_18// `fixedSizedExample` still remains as ["ABC", "XYZYX", "PQR"]_18_18// Invalid: Map using a function which accepts a different type._18// This results in a type error, as the array contains `String` values while function accepts_18// `Bool`._18let functionAcceptingBool =_18fun (_ x: Bool): Int {_18return 0_18}_18let invalidMapFunctionExample = fixedSizedExample.map(functionAcceptingBool) -
_10access(all)_10view fun filter(_ f: view fun(T): Bool): [T]
Returns a new array whose elements are filtered by applying the filter function on each element of the original array. Available if
T
is not resource-kinded._18let example = [1, 2, 3]_18let trueForEven =_18fun (_ x: Int): Bool {_18return x % 2 == 0_18}_18_18let filteredExample: [Int] = example.filter(trueForEven)_18// `filteredExample` is `[2]`_18// `example` still remains as `[1, 2, 3]`_18_18// Invalid: Filter using a function which accepts a different type._18// This results in a type error, as the array contains `Int` values while function accepts_18// `Int64`._18let functionAcceptingInt64 =_18fun (_ x: Int64): Bool {_18return x % 2 == 0_18}_18let invalidFilterFunctionExample = example.filter(functionAcceptingInt64)The
filter
function is also available for fixed-sized arrays:_10access(all)_10view fun filter(_ f: view fun(T): Bool): [T]Returns a new variable-sized array whose elements are filtered by applying the filter function on each element of the original array. Available if
T
is not resource-kinded._18let fixedSizedExample: [String; 3] = ["AB", "XYZYX", "PQR"]_18let lengthOfStringGreaterThanTwo =_18fun (_ x: String): Bool {_18return x.length > 2_18}_18_18let fixedArrayFilteredExample = fixedSizedExample.filter(lengthOfStringGreaterThanTwo)_18// `fixedArrayFilteredExample` is `["XYZYX", "PQR"]`_18// `fixedSizedExample` still remains as ["AB", "XYZYX", "PQR"]_18_18// Invalid: Filter using a function which accepts a different type._18// This results in a type error, as the array contains `String` values while function accepts_18// `Bool`._18let functionAcceptingBool =_18fun (_ x: Bool): Bool {_18return True_18}_18let invalidFilterFunctionExample = fixedSizedExample.filter(functionAcceptingBool)
Variable-size array functions
The following functions can only be used on variable-sized arrays. It is invalid to use one of these functions on a fixed-sized array.
-
_10access(Mutate | Insert)_10fun append(_ element: T): Void
Adds the new element
element
of typeT
to the end of the array.The new element must be the same type as all the other elements in the array.
This function mutates the array.
_10// Declare an array of integers._10let numbers = [42, 23, 31, 12]_10_10// Add a new element to the array._10numbers.append(20)_10// `numbers` is now `[42, 23, 31, 12, 20]`_10_10// Invalid: The parameter has the wrong type `String`._10numbers.append("SneakyString") -
_10access(Mutate | Insert)_10fun appendAll(_ array: T): Void
Adds all the elements from
array
to the end of the array the function is called on.Both arrays must be the same type
T
.This function mutates the array.
_10// Declare an array of integers._10let numbers = [42, 23]_10_10// Add new elements to the array._10numbers.appendAll([31, 12, 20])_10// `numbers` is now `[42, 23, 31, 12, 20]`_10_10// Invalid: The parameter has the wrong type `[String]`._10numbers.appendAll(["Sneaky", "String"]) -
_10access(Mutate | Insert)_10fun insert(at: Int, _ element: T): Void
Inserts the new element
element
of typeT
at the givenindex
of the array.The new element must be of the same type as the other elements in the array.
The
index
must be within the bounds of the array. If the index is outside the bounds, the program aborts.The existing element at the supplied index is not overwritten.
All the elements after the new inserted element are shifted to the right by one.
This function mutates the array.
_10// Declare an array of integers._10let numbers = [42, 23, 31, 12]_10_10// Insert a new element at position 1 of the array._10numbers.insert(at: 1, 20)_10// `numbers` is now `[42, 20, 23, 31, 12]`_10_10// Run-time error: Out of bounds index, the program aborts._10numbers.insert(at: 12, 39) -
_10access(Mutate | Remove)_10fun remove(at: Int): T
Removes the element at the given
index
from the array and returns it.The
index
must be within the bounds of the array. If the index is outside the bounds, the program aborts.This function mutates the array.
_10// Declare an array of integers._10let numbers = [42, 23, 31]_10_10// Remove element at position 1 of the array._10let twentyThree = numbers.remove(at: 1)_10// `numbers` is now `[42, 31]`_10// `twentyThree` is `23`_10_10// Run-time error: Out of bounds index, the program aborts._10numbers.remove(at: 19) -
_10access(Mutate | Remove)_10fun removeFirst(): T
Removes the first element from the array and returns it.
The array must not be empty. If the array is empty, the program aborts.
This function mutates the array.
_15// Declare an array of integers._15let numbers = [42, 23]_15_15// Remove the first element of the array._15let fortytwo = numbers.removeFirst()_15// `numbers` is now `[23]`_15// `fortywo` is `42`_15_15// Remove the first element of the array._15let twentyThree = numbers.removeFirst()_15// `numbers` is now `[]`_15// `twentyThree` is `23`_15_15// Run-time error: The array is empty, the program aborts._15numbers.removeFirst() -
_10access(Mutate | Remove)_10fun removeLast(): T
Removes the last element from the array and returns it.
The array must not be empty. If the array is empty, the program aborts.
This function mutates the array.
_15// Declare an array of integers._15let numbers = [42, 23]_15_15// Remove the last element of the array._15let twentyThree = numbers.removeLast()_15// `numbers` is now `[42]`_15// `twentyThree` is `23`_15_15// Remove the last element of the array._15let fortyTwo = numbers.removeLast()_15// `numbers` is now `[]`_15// `fortyTwo` is `42`_15_15// Run-time error: The array is empty, the program aborts._15numbers.removeLast()