Taking and changing an element
The index in brackets, .length to count, and the first error of this course that only happens at run time.
An array is not traversed from start to finish alone. Each of its elements has an index, and that index is enough to reach it.
@entry(start)
object MyProgram {
start() {
var temperatures := [12, 19, 7];
Console.print(text: $"the first: {temperatures[0]}");
Console.print(text: $"the last: {temperatures[-1]}");
Console.print(text: $"how many: {temperatures.length}");
temperatures[1] := 20;
Console.print(text: $"the second, corrected: {temperatures[1]}");
}
}
The index is written in brackets
temperatures[0]
The same brackets that built the array serve to draw from it. temperatures[0] is the first
element — not the second.
Indexes start at zero, and that is not an inherited oddity: an index is not a count, it is a
distance from the start. The first element is zero steps from the start, the second one step.
Hold it in that form and you will not get it wrong again: temperatures[2] is two steps from the
start, so it is the third.
.length counts
temperatures.length
Three elements, so 3. It is a member, not a method: no parentheses. And it holds for a text
too — "Simon".length gives 5.
Counting from the end
The last element is written temperatures[-1], the one before it temperatures[-2].
The minus sign does not mean “go back”: it says which end you count from. A positive index is
a distance from the start, a negative one a distance from the end. -1 is therefore the first
element counting backwards — there is no -0, since zero is already taken by the other end.
The long form still exists, and it is worth understanding:
temperatures[temperatures.length - 1]
That is exactly what temperatures[-1] means, and what the compiler writes in your place: three
elements, indexes 0, 1 and 2, so the last index is length - 1, never length. The direct
consequence of indexes starting at zero.
The number has to be written. temperatures[-1] is rewritten at compile time, so it costs
nothing at run time — but an index you compute that turns out negative is still out of bounds:
var rank := 0 - 1;
temperatures[rank] // IndexOutOfRangeError, not the last element
The asymmetry is deliberate. Normalising a computed index would mean reading the length and testing the sign on every access, on the type the language promises to cost what a C array costs.
Changing an element
temperatures[1] := 20;
The := of section 2.1, except that it aims at a slot of the array rather than at a variable.
temperatures now holds [12, 20, 7].
But an array does not grow. The literal fixes its contents: you may change a value, not add a fourth one. There is no method for that, and the ambient library offers none — an array has the size you gave it when you wrote it.
Going out of bounds
Ask for temperatures[5] of an array holding three:
uncaught error — IndexOutOfRangeError : index 5 out of range for an array of length 3
The message gives the two numbers that matter: the one asked for, and the one available.
This is the first error in this course that happens only at run time. Everything refused so far was refused by the compiler, before the program ran. Here it can do nothing for you: the index it is given is often computed, and its value is known only when the line runs.
Keeping the index within bounds is therefore up to you. The next subsection shows the safe way to do it when you go through them all.
Your turn
- Print
temperatures[3]: three elements, but no index 3. Read the error. - Print
temperatures[temperatures.length]— the same mistake written differently, and the same refusal. That is exactly why the last index is writtenlength - 1, or-1. - Print
temperatures[-4]of an array holding three: counting from the end does not excuse you from the bounds. Look closely at the index the error names — it is-1, not-4. The compiler has already rewritten-4intotemperatures.length - 4, that is3 - 4. The error shows you the index that was really asked for. - Change
temperatures[0]before the three prints and check that the first line follows. - Count the letters of a text:
Console.print(text: $"{"Simon Magus".length}");