Indexers

An indexer expression is used to access sub-items of an expression at a specific index. Expressions that can be index include Arrays, Indexed Properties or objects with a Default Indexers and Tuples.

An indexer expression consists of a pair of square brackets ([]) containing one or more expressions, separated by comma. The number and type of the expressions depends on the definition of the indexed expression.

var x := lMyArray[5, 8];
var y := lDictionary['Foo'];
var z := lMyTuple[1];

Arrays

Arrays can have one or more dimension, and when indexing the array as many indexer expressions can be provided as there are dimensions. If the number of indexes matches the number of dimension, an array element is the result; if fewer expressions are provided, the result is a sub-array with the remaining dimension(s).

Imagine an var a := array [0..9, 0..9] of String. This can be thought of as a square of 100 string values, or ten rows with ten columns each.

Indexing the array with two indexer expressions accesses one specific string. a[0,0] is the very first string, and a[9,9] the very last. a[0,9] is the last string oin the first column, while a[9,0] is the first string of the last column.

(which index represents the "column" and which one the "row" is completely arbitrary, of course, and depends on the semantics behind the actual data in the array).

Indexing the array with a single expression will return a subarray, one individual row of the array. a[0] ios the first row (an array [0..9] of String, itself), while a[9] is the last row.

Of course, sub-arrays can be indexed themsleves, so a[0][9] will index the first row, and then index the last element in it, essentially being equivalent to a[0,9].

var a := array [0..9, 0..9] of String;

var first := a[0, 0];
var last := a[9, 9];
var x := a[0, 9];
var y := a[9, 0];

var sub := a[0]; // sub is an array[0..9] iof String
last z := sub[9]; // same as a[0,9]

Arrays are always indexed with an Integer, Enum or Boolean type, depending on how the array was defined. Each dimension of an array can start at 0 (the default), or at an arbitrary start value specified when declaring the array, and must fit within the bounds of the array.

Indexer Properties

Indexed Properties are a special kind of properties, that look similar to an array, when being used, but under the hood provide their own code to access and store individual items.

Like Arrays, indexer properties can define one or more parameter, or dimensions, but unlike arrays, these parameters can be of any type, including non-numeric ones. Also unlike arrays, accessing an indexed property always requires all parameters, one cannot obtain a "slice" of a multi-dimensional indexed property.

property Languages[aName: String]: String; ...

...

var x := Languages['Swift'];

Default Indexers

Default Indexers are essentially the same as Indexed Properties, with the special provision that the name of the property can be omitted and the Type containing the property itself can be indexed.

Essentially this is just a convenient shortcut to omit the name of the property but it allows for cleaner and richer APIs, especially for objects where the indexed data is their main purpose (such as a List or a Dictionary class, for example:

var lNames := new List<String>;
...
var y := lNames.Count;
var x := lNames[5];

var z := lNames.Items[5]; // more verbose and less intuitive

Tuples

Individual members of a Tuple can also be accessed via an indexer expression. Tuples are always indexed with an constant integer expression, starting at zero and ending one value below the number of items in the tuple. The result is strognly typed to the particular member of the tuple.

var t := (1, 'Hello', true);
var a := t[0]; // a is an Integer
var b := t[1]; // b is a String
var c := t[2]; // c is a Boolean
var d := t[a]; // 🛑 Compiler error - tuple index must be constant

Writing to Indexer Expressions

Assuming the underlying expression is not read-only, indexers can be assigned to, to change an individual value of the expression.

a[5,5] := 'Center(ish)';
p['Oxygene'] := 'My favorite propgramming language';
t[1] := 5;

See Also