This commit is contained in:
2026-09-13 00:12:41 +02:00
parent fd4e879c0c
commit 019c8ad335
16 changed files with 580 additions and 92 deletions

View File

@@ -1,26 +1,159 @@
# 22. Collections et itération
## 22.1 `Array<T>` — V1 REQUIS — DIRECTION FIGÉE
## 22.1 `Array<T>` — V1 REQUIS — FIGÉ EN PRINCIPE
`Array<T>` est une séquence contiguë dont la taille est fixée lors de la création et n'est pas redimensionnable.
`Array<T>` est une séquence contiguë dont la longueur est déterminée au runtime lors de la construction et reste fixe ensuite.
## 22.2 `StaticArray<T,N>` — V1 REQUIS — DIRECTION FIGÉE
Il n'expose pas d'opération structurelle de redimensionnement.
`StaticArray<T,N>` est un tableau à taille connue à la compilation.
Le mécanisme exact de const generics nécessaire à `N` doit être défini avec les generics.
## 22.3 Collection redimensionnable — V1 REQUIS — À FINALISER
Un type du type :
Les éléments suivent exactement la sémantique normale de `T` :
```text
Vector<T>
T primitif -> valeur by-value
T struct -> valeur by-value
T class -> référence de classe
```
est envisagé pour les séquences redimensionnables, mais l'API et le nom final doivent être figés dans le SDK V1.
Copier un `Array<T>` crée une collection indépendante. Les éléments eux-mêmes sont copiés selon la sémantique normale de `T`.
## 22.4 `Iterable<T>` / `Iterator<T>` — V1 REQUIS — FIGÉ
Pour `Array<User>`, deux arrays copiés peuvent donc contenir des références vers les mêmes objets `User`, tout en restant indépendants quant au remplacement de leurs cases.
### 22.1.1 Initialisation complète
Un `Array<T>` safe doit être entièrement initialisé avant de devenir observable.
Il n'existe aucune initialisation implicite en zéro, `null`, `None` ou valeur indéfinie.
```text
Array<int32> values = [1, 2, 3];
Array<int32> empty = [];
```
Le littéral `[...]` est contextualisé par le type attendu ; il ne reçoit pas automatiquement un type autonome hors contexte suffisant.
Les expressions d'un littéral d'array sont évaluées exactement une fois, de gauche à droite. En cas d'échec pendant la construction, aucun array partiellement initialisé ne devient observable.
### 22.1.2 `filled`
```text
Array<T>::filled(uint64 length, T value)
```
`value` est évaluée une seule fois, puis répétée selon la sémantique normale de copie de `T`.
```text
User firstUser = ...;
User otherUser = ...;
Array<User> users = Array<User>::filled(3, firstUser);
users[1] = otherUser; // OK si l'accès n'est pas const
```
Initialement, les trois cases contiennent la même référence `firstUser`. Chaque case reste cependant un emplacement indépendant et peut recevoir ultérieurement une autre référence.
`filled()` ne clone jamais implicitement un objet référencé.
### 22.1.3 `empty` et `generate`
```text
Array<T>::empty()
```
construit un array de longueur zéro.
Une opération `generate` est retenue conceptuellement pour construire une valeur distincte par index. Sa syntaxe exacte sera figée avec les callables/lambdas.
La factory devra être appelée exactement une fois par index, dans l'ordre croissant, sans parallélisation implicite.
Le safe code ne peut pas obtenir un `Array<T>` observable partiellement/non initialisé. Le compilateur/runtime reste libre d'utiliser de la mémoire non initialisée en interne tant qu'elle n'est jamais observable.
## 22.2 `StaticArray<T,N>` — V1 REQUIS — FIGÉ
`StaticArray<T,N>` est une séquence contiguë dont la longueur `N` est connue à la compilation et reste fixe.
```text
StaticArray<int32, 3> values = [10, 20, 30];
StaticArray<int32, 0> empty = [];
```
Le nombre d'éléments du littéral doit correspondre exactement à `N`.
Une initialisation répétée utilise :
```text
StaticArray<T,N>::filled(T value)
```
avec la même sémantique de copie que `Array<T>::filled`.
`StaticArray<T,N>` n'autorise pas davantage qu'`Array<T>` l'observation d'éléments non initialisés.
## 22.3 `Slice<T>` — V1 REQUIS — FIGÉ EN PRINCIPE
`Slice<T>` est une vue contiguë, de longueur fixe, sur une portion d'un stockage existant.
Une slice ne réalise aucune copie sémantique des éléments.
```text
Array<int32> values = ...;
Slice<int32> part = values::slice(10..<20);
part[0] = 42; // modifie values[10]
```
Une slice :
```text
reste attachée à la portion qu'elle désigne
conserve une longueur fixe
n'est pas redimensionnable
n'est pas déplaçable vers une autre portion
peut modifier les éléments uniquement si l'accès source l'autorise
ne peut jamais augmenter les droits de mutabilité de la source
```
La constness se propage :
```text
const Array<User> users = ...;
const Slice<User> part = users::slice(0..<4);
part[0] = otherUser; // ERROR
part[0]::setName("Alice"); // ERROR
part[0]::getName(); // OK
```
Le backing storage nécessaire à une slice reste vivant aussi longtemps que nécessaire. Cette garantie ne requiert aucune syntaxe de lifetime utilisateur.
Une slice vide est une valeur valide.
Les indices d'une sous-slice sont relatifs à la slice source.
`Slice<T>` garantit la contiguïté. Une éventuelle vue non contiguë constituerait un autre concept et n'est pas réservée sans besoin réel.
## 22.4 Interfaces de collections — V1 REQUIS — FIGÉ EN PRINCIPE
Les interfaces décrivent des capacités réellement garanties. Les classes/structs génériques fournissent le stockage et l'implémentation.
Saselang ne retient pas le modèle d'opérations optionnelles qui existent dans une interface mais échouent ensuite au runtime comme « unsupported ».
Hiérarchie principale retenue :
```text
Iterable<T>
Collection<T>
List<T>
SettableList<T>
ResizableList<T>
```
`Set<T>` et `Map<K,V>` sont des branches distinctes à préciser.
### 22.4.1 `Iterable<T>` / `Iterator<T>`
Interfaces Core reconnues par `foreach`.
@@ -28,6 +161,107 @@ Elles ne portent pas le préfixe `Op`, car `foreach` est une construction du lan
Indexabilité et itérabilité sont indépendantes.
### 22.4.2 `Collection<T>`
`Collection<T>` étend `Iterable<T>` et représente une collection finie d'éléments.
Contrat minimal retenu :
```text
count() -> uint64
isEmpty() -> bool
contains(const T value) -> bool
```
`count()` exprime le nombre d'éléments au sens général de collection.
### 22.4.3 `List<T>`
`List<T>` étend `Collection<T>` et `OpIndex<uint64,T>`.
Elle garantit :
```text
ordre stable
indexation positionnelle en lecture
length() -> uint64
```
Pour une `List<T>` :
```text
count() == length()
```
Les deux noms sont néanmoins conservés parce qu'ils expriment des concepts différents : cardinalité générale de collection et longueur d'une séquence indexable.
`List<T>` ne garantit ni remplacement d'un élément, ni redimensionnement, ni complexité algorithmique particulière de l'accès indexé.
### 22.4.4 `SettableList<T>`
`SettableList<T>` étend `List<T>` et `OpIndexMut<uint64,T>`.
Elle garantit le remplacement d'un élément existant sans modification de la longueur.
```text
list[index] = value;
```
ne signifie jamais `append` lorsque `index == length()`.
### 22.4.5 `ResizableList<T>`
`ResizableList<T>` étend `SettableList<T>`.
Elle garantit des opérations structurelles capables de modifier la longueur, par exemple ajout, insertion et suppression.
Les signatures exactes seront figées lors de la définition du type concret redimensionnable.
Un `resize(newLength)` sans information d'initialisation n'est pas retenu implicitement : agrandir une collection doit toujours définir comment les nouveaux éléments sont construits.
### 22.4.6 Capacité du type et permission `const`
La capacité intrinsèque du type et la permission d'un accès sont deux dimensions distinctes.
```text
SettableList<User> users = ...;
const SettableList<User> readonly = users;
```
Le type sait remplacer des éléments, mais l'accès `readonly` ne peut pas utiliser cette capacité.
La propagation générale de `const` reste applicable aux éléments obtenus via cet accès.
### 22.4.7 Classification initiale
```text
StaticArray<T,N>
List<T>
SettableList<T>
pas ResizableList<T>
Array<T>
List<T>
SettableList<T>
pas ResizableList<T>
Slice<T>
List<T>
SettableList<T>
pas ResizableList<T>
Vector<T>
List<T>
SettableList<T>
ResizableList<T>
```
`Vector<T>` reste à définir précisément.
Un type persistant/immutable par nature n'a aucune obligation d'implémenter `List<T>`. Par exemple, un futur `PersistentList<T>` peut implémenter uniquement `Collection<T>` et fournir ses propres opérations si cela correspond mieux à sa sémantique.
Une interface Saselang n'est jamais implémentée uniquement parce qu'un type ressemble conceptuellement à une autre famille de types.
## 22.5 `Range<T>` — V1 REQUIS — FIGÉ EN PRINCIPE
`Range<T>` est une vraie valeur Saselang immuable représentant un intervalle ordonné. Il ne représente ni un pas ni une progression d'itération.