Section 6.1

Prendre et changer un élément

Le rang entre crochets, .length pour compter, et la première erreur du cours qui n'arrive qu'à l'exécution.

Un tableau ne se parcourt pas seulement du début à la fin. Chacun de ses éléments a un rang, et ce rang suffit à l’atteindre.

@entry(demarrer)
object MonProgramme {
    demarrer() {
        var mesures := [12, 19, 7];

        Console.print(text: $"la première : {mesures[0]}");
        Console.print(text: $"la dernière : {mesures[-1]}");
        Console.print(text: $"combien : {mesures.length}");

        mesures[1] := 20;

        Console.print(text: $"la deuxième, corrigée : {mesures[1]}");
    }
}

Le rang s’écrit entre crochets

mesures[0]

Les mêmes crochets qui ont construit le tableau servent à y puiser. mesures[0] est le premier élément — pas le deuxième.

Le rang part de zéro, et ce n’est pas une bizarrerie héritée : un rang n’est pas un compte, c’est une distance depuis le début. Le premier élément est à zéro pas du début, le deuxième à un pas. Retenez-le sous cette forme et vous ne vous tromperez plus : mesures[2] est à deux pas du début, donc c’est le troisième.

.length compte

mesures.length

Trois éléments, donc 3. C’est un membre, pas une méthode : pas de parenthèses. Et il vaut aussi pour un texte — "Simon".length rend 5.

Compter depuis la fin

Le dernier élément s’écrit mesures[-1], l’avant-dernier mesures[-2].

Le signe moins ne dit pas « recule » : il dit de quel côté on compte. Un rang positif est une distance depuis le début, un rang négatif une distance depuis la fin. -1 est donc le premier élément en partant de la fin — il n’y a pas de -0, puisque zéro est déjà pris par l’autre bout.

La forme longue existe toujours, et elle vaut d’être comprise :

mesures[mesures.length - 1]

C’est exactement ce que mesures[-1] veut dire, et ce que le compilateur écrit à votre place : trois éléments, rangs 0, 1 et 2, donc le dernier rang est length - 1, jamais length. La conséquence directe du rang qui part de zéro.

Le nombre doit être écrit. mesures[-1] est réécrit à la compilation, donc il ne coûte rien à l’exécution — mais un rang qu’on calcule et qui se trouve être négatif reste hors des bornes :

var rang := 0 - 1;
mesures[rang]        // IndexOutOfRangeError, pas le dernier élément

L’asymétrie est voulue. Normaliser un rang calculé demanderait de lire la longueur et de tester le signe à chaque accès, sur le type que le langage promet aussi rapide qu’un tableau C.

Changer un élément

mesures[1] := 20;

Le := de la section 2.1, à ceci près qu’il vise une case du tableau plutôt qu’une variable. mesures contient désormais [12, 20, 7].

Mais un tableau ne grandit pas. Le littéral fixe son contenu : vous pouvez changer une valeur, pas en ajouter une quatrième. Il n’y a pas de méthode pour cela, et la bibliothèque ambiante n’en propose pas — un tableau a la taille qu’on lui a donnée en l’écrivant.

Sortir des bornes

Demandez mesures[5] d’un tableau qui en compte trois :

uncaught error — IndexOutOfRangeError : index 5 out of range for an array of length 3

Le message dit les deux nombres qui comptent : celui qu’on a demandé, et celui qu’on avait.

C’est la première erreur de ce cours qui n’arrive qu’à l’exécution. Tout ce qui a été refusé jusqu’ici l’était par le compilateur, avant que le programme tourne. Ici il ne peut rien pour vous : le rang qu’on lui donne est souvent calculé, et sa valeur ne se connaît qu’au moment où la ligne s’exécute.

C’est donc à vous de tenir le rang dans les bornes. La sous-section suivante montre la façon sûre de le faire quand on les parcourt tous.

À vous

  • Affichez mesures[3] : trois éléments, mais aucun rang 3. Lisez l’erreur.
  • Affichez mesures[mesures.length] — même faute, écrite autrement, et le même refus. C’est exactement pourquoi le dernier rang s’écrit length - 1, ou -1.
  • Affichez mesures[-4] d’un tableau qui en compte trois : compter depuis la fin ne dispense pas des bornes. Regardez bien le rang que l’erreur nomme — c’est -1, pas -4. Le compilateur a déjà réécrit -4 en mesures.length - 4, soit 3 - 4. L’erreur vous montre le rang qui a vraiment été demandé.
  • Changez mesures[0] avant les trois affichages et vérifiez que la première ligne suit.
  • Comptez les lettres d’un texte : Console.print(text: $"{"Simon Magus".length}");