The third type of Cicada variable is an array variable, which is simply N copies of some other variable type. To define an array we write N inside square brackets before the type we want to copy. Multi-dimensional arrays are just arrays of arrays. Here are some examples.
numDays :: [12] int
checkerboard :: [8][8] bool
coordinates :: [] { x :: y :: double }
Notice that coordinates was defined without a specific array size, so it will start off as a size-0 array until it is manually resized. Arrays defined using empty brackets (or equivalently with the [*] symbol) are given extra storage so that elements can be added easily. Use empty brackets for arrays that will be resized often.
We access array elements using square brackets after the array name, just as in C. The last element can be accessed using the keyword top. To access a range of elements a through b, write [<a, b>]. To access all elements we can simply write [*] or [].
numDays[1] = 31 | assign a single element
numDays[<2, 4>] = { 31, 31, 30 } | assign 3 elements
checkerboard[1][1] = checkerboard[1][3] = true | assign 2 elements
checkerboard[3] = checkerboard[1] | assign a whole row of elements
checkerboard[top] = checkerboard[top-2] | ditto for the 6th and 8th rows
coordinates[*].x = coordinates[*].y | assign all 'x's
coordinates[*].y = -1 | assign all 'y's (scalar-to-array copying)
Strings are effectively character arrays, and we can use array operators to access either single characters or ranges of characters. The single-element operator [n] returns a character, whereas the multi-index operator [<a, b>] returns a character array (equivalent to a string). Given two strings s1 and s2, the following commands are legal: s1 = s2[<3, 4>], s1 = s2[<4, 4>], s1 =! s2[4]; however s1 = s2[4] is illegal since Cicada does not allow char-to-string assignment. Note that array operators only work on string variables, not string literals, so "abc"[2] will cause an error.
Cicada has a technical restriction on the elements we can access simultaneously in multi-dimensional arrays: their memory has to be contiguous. Internally, the last index counts consecutive elements in memory; then the next-to-last index increments; etc. So the elements of some 2-dimensional array A elements are [1][1], [1][2], ..., [2][1], [2][2], ..., etc as shown in Figure 1. Here are some legal and illegal expressions involving a matrix A :: [3][4] { x :: ... }:
A[<2, 3>] | legal
A[<2, 3>][<1, 4>] | legal
A[<2, 3>][2] | will cause error
A[2][<2, 3>] | legal
A[1][2] | legal of course
A[<2, 3>][*].x | legal -- x is stored separately from other members
When we address part of an array using two or more [*] operators, Cicada loses track of how many elements were in each dimension and pretends that it is looking at a one-dimensional list. For example, if we define:
grid :: [5][5] int
then both grid and grid[*] refer to a 2-dimensional array, but grid[*][*] is effectively a single 1-dimensional list of 25 elements. This is another technical limitation of Cicada, and it may change in the future.
Last update: May 8, 2024