v0.2.17
This commit is contained in:
@@ -135,9 +135,9 @@ Les indices d'une sous-slice sont relatifs à la slice source.
|
||||
|
||||
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 ».
|
||||
Saselang ne retient pas le modèle d'opérations optionnelles présentes dans une interface mais susceptibles d'échouer ensuite comme « unsupported ».
|
||||
|
||||
Hiérarchie principale retenue :
|
||||
Hiérarchie principale :
|
||||
|
||||
```text
|
||||
Iterable<T>
|
||||
@@ -151,21 +151,84 @@ SettableList<T>
|
||||
ResizableList<T>
|
||||
```
|
||||
|
||||
`Set<T>` et `Map<K,V>` sont des branches distinctes à préciser.
|
||||
`Set<T>` et `Map<K,V>` forment des branches sémantiques distinctes.
|
||||
|
||||
### 22.4.1 `Iterable<T>` / `Iterator<T>`
|
||||
### 22.4.1 `Iterable<T>` et `Iterator<T>`
|
||||
|
||||
Interfaces Core reconnues par `foreach`.
|
||||
`foreach` dépend uniquement de `Iterable<T>`.
|
||||
|
||||
Elles ne portent pas le préfixe `Op`, car `foreach` est une construction du langage et non un opérateur symbolique.
|
||||
```text
|
||||
interface Iterable<T> {
|
||||
const method iterator() -> Iterator<T>;
|
||||
}
|
||||
```
|
||||
|
||||
Indexabilité et itérabilité sont indépendantes.
|
||||
Créer un iterator ne constitue pas une mutation sémantique de la source.
|
||||
|
||||
### 22.4.2 `Collection<T>`
|
||||
`Iterator<T>` représente une itération particulière et possède un état de progression mutable :
|
||||
|
||||
```text
|
||||
interface Iterator<T> {
|
||||
method next() -> Option<T>;
|
||||
}
|
||||
```
|
||||
|
||||
`Some(value)` fournit l'élément suivant ; `None` marque la fin normale de l'itération.
|
||||
|
||||
Saselang n'impose pas le couple `hasNext()` / `next()`. `Option<T>` rend l'état de fin explicite dans une seule opération.
|
||||
|
||||
`Iterator<T>` n'étend pas `Iterable<T>` par défaut. Une source capable de créer des itérations et une itération déjà en cours sont deux capacités différentes, même si certains types concrets peuvent éventuellement fournir les deux.
|
||||
|
||||
Pour les collections ordinaires non concurrentes, une mutation structurelle invalide par défaut les iterators actifs lorsque le type concret ne garantit pas explicitement une autre politique.
|
||||
|
||||
```text
|
||||
insert / remove / clear / append / changement structurel
|
||||
-> peut invalider l'iterator
|
||||
|
||||
utilisation ultérieure d'un iterator invalidé
|
||||
-> IteratorInvalidatedFault
|
||||
```
|
||||
|
||||
Le simple remplacement d'une valeur existante n'est pas automatiquement une mutation structurelle. Le type concret documente sa politique exacte.
|
||||
|
||||
Les collections concurrentes ou spécialisées peuvent fournir une autre politique (`snapshot`, stabilité, weak consistency, etc.) ; elle doit être explicite.
|
||||
|
||||
### 22.4.2 `View<T>`
|
||||
|
||||
`View<T>` représente une vue légère sur une source existante :
|
||||
|
||||
```text
|
||||
interface View<T> extends Iterable<T> {
|
||||
const method count() -> uint64;
|
||||
const method isEmpty() -> bool;
|
||||
}
|
||||
```
|
||||
|
||||
`View<T>` n'étend pas `Collection<T>`.
|
||||
|
||||
Le contrat général ne contient pas `contains()`. Une classe ou une interface plus spécialisée peut l'ajouter si elle en a réellement besoin.
|
||||
|
||||
Une `View<T>` :
|
||||
|
||||
```text
|
||||
n'impose aucune copie des éléments
|
||||
n'impose aucun stockage indépendant
|
||||
n'impose aucune contiguïté
|
||||
ne possède pas nécessairement les données qu'elle expose
|
||||
ne peut jamais augmenter les permissions const de sa source
|
||||
```
|
||||
|
||||
Par défaut, une vue est **vivante**, pas un snapshot : une nouvelle itération peut observer les modifications ultérieures de la source selon le contrat du type concret.
|
||||
|
||||
Le runtime/compilateur garantit que le stockage ou l'état source nécessaire reste valide aussi longtemps que la vue l'exige, sans syntaxe de lifetime utilisateur.
|
||||
|
||||
Le comportement d'un iterator déjà créé avant une modification reste régi par la politique d'invalidation/stabilité du type concret.
|
||||
|
||||
### 22.4.3 `Collection<T>`
|
||||
|
||||
`Collection<T>` étend `Iterable<T>` et représente une collection finie d'éléments.
|
||||
|
||||
Contrat minimal retenu :
|
||||
Contrat minimal :
|
||||
|
||||
```text
|
||||
count() -> uint64
|
||||
@@ -175,7 +238,7 @@ contains(const T value) -> bool
|
||||
|
||||
`count()` exprime le nombre d'éléments au sens général de collection.
|
||||
|
||||
### 22.4.3 `List<T>`
|
||||
### 22.4.4 `List<T>`
|
||||
|
||||
`List<T>` étend `Collection<T>` et `OpIndex<uint64,T>`.
|
||||
|
||||
@@ -193,33 +256,39 @@ Pour une `List<T>` :
|
||||
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.
|
||||
Les deux noms restent distincts parce qu'ils expriment la cardinalité générale d'une collection et la 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é.
|
||||
`List<T>` ne garantit ni remplacement, ni redimensionnement, ni complexité algorithmique particulière de l'accès indexé.
|
||||
|
||||
### 22.4.4 `SettableList<T>`
|
||||
### 22.4.5 `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.
|
||||
Elle garantit le remplacement d'un élément existant sans modification de longueur :
|
||||
|
||||
```text
|
||||
list[index] = value;
|
||||
```
|
||||
|
||||
ne signifie jamais `append` lorsque `index == length()`.
|
||||
`index` doit désigner une case existante ; l'affectation ne signifie jamais `append`.
|
||||
|
||||
### 22.4.5 `ResizableList<T>`
|
||||
### 22.4.6 `ResizableList<T>`
|
||||
|
||||
`ResizableList<T>` étend `SettableList<T>`.
|
||||
`ResizableList<T>` étend `SettableList<T>` et garantit des opérations structurelles capables de modifier la longueur.
|
||||
|
||||
Elle garantit des opérations structurelles capables de modifier la longueur, par exemple ajout, insertion et suppression.
|
||||
Les signatures exactes seront figées avec `Vector<T>`.
|
||||
|
||||
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 définir comment les nouveaux éléments sont construits.
|
||||
|
||||
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.
|
||||
Lorsqu'il existe, `clear()` suit la convention :
|
||||
|
||||
### 22.4.6 Capacité du type et permission `const`
|
||||
```text
|
||||
clear() -> uint64
|
||||
```
|
||||
|
||||
et retourne le nombre d'éléments effectivement supprimés.
|
||||
|
||||
### 22.4.7 Capacité du type et permission `const`
|
||||
|
||||
La capacité intrinsèque du type et la permission d'un accès sont deux dimensions distinctes.
|
||||
|
||||
@@ -230,9 +299,9 @@ 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.
|
||||
La même règle s'applique à `Map`, `Set`, `View` et aux éléments obtenus à travers ces accès : une projection ne peut jamais augmenter les droits reçus de sa source.
|
||||
|
||||
### 22.4.7 Classification initiale
|
||||
### 22.4.8 Classification initiale des séquences
|
||||
|
||||
```text
|
||||
StaticArray<T,N>
|
||||
@@ -258,9 +327,271 @@ Vector<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.
|
||||
Un type persistant/immutable par nature n'a aucune obligation d'implémenter `List<T>` s'il ne garantit pas 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.4.9 `Set<T>` et `ResizableSet<T>`
|
||||
|
||||
`Set<T>` étend `Collection<T>`.
|
||||
|
||||
Il garantit :
|
||||
|
||||
```text
|
||||
unicité des éléments
|
||||
aucun index ordinal
|
||||
aucun ordre d'itération général garanti
|
||||
```
|
||||
|
||||
La capacité structurelle est séparée :
|
||||
|
||||
```text
|
||||
interface ResizableSet<T> extends Set<T> {
|
||||
method add(T value) -> bool;
|
||||
method remove(const T value) -> bool;
|
||||
method clear() -> uint64;
|
||||
}
|
||||
```
|
||||
|
||||
Sémantique :
|
||||
|
||||
```text
|
||||
add(value)
|
||||
true -> élément ajouté
|
||||
false -> élément déjà présent, set inchangé
|
||||
|
||||
remove(value)
|
||||
true -> élément supprimé
|
||||
false -> élément absent
|
||||
|
||||
clear()
|
||||
-> nombre d'éléments effectivement supprimés
|
||||
```
|
||||
|
||||
Il n'existe pas de niveau `SettableSet<T>` : remplacer un élément d'un set équivaut conceptuellement à une modification structurelle de son ensemble de valeurs.
|
||||
|
||||
### 22.4.10 `Map<K,V>`, `SettableMap<K,V>` et `ResizableMap<K,V>`
|
||||
|
||||
`Map<K,V>` n'étend pas `Collection<T>` et n'implémente pas directement `Iterable<...>`. Une map possède trois projections naturelles différentes : clés, valeurs et entrées ; aucune ne doit être choisie implicitement comme itération « par défaut ».
|
||||
|
||||
Contrat de lecture :
|
||||
|
||||
```text
|
||||
interface Map<K,V> extends OpIndex<K,V> {
|
||||
const method count() -> uint64;
|
||||
const method isEmpty() -> bool;
|
||||
const method containsKey(const K key) -> bool;
|
||||
const method get(const K key) -> Option<V>;
|
||||
|
||||
const method keys() -> View<K>;
|
||||
const method values() -> View<V>;
|
||||
const method entries() -> View<MapEntry<K,V>>;
|
||||
}
|
||||
```
|
||||
|
||||
Deux intentions sont séparées :
|
||||
|
||||
```text
|
||||
map[key] -> V
|
||||
accès strict
|
||||
la clé doit exister
|
||||
absence dynamique -> KeyNotFoundFault
|
||||
|
||||
map::get(key) -> Option<V>
|
||||
accès conditionnel
|
||||
absence normale -> None
|
||||
```
|
||||
|
||||
`SettableMap<K,V>` étend `Map<K,V>` et `OpIndexMut<K,V>`.
|
||||
|
||||
```text
|
||||
map[key] = value;
|
||||
```
|
||||
|
||||
remplace uniquement la valeur d'une clé existante. Cette syntaxe n'insère jamais implicitement une nouvelle clé. Une clé absente produit `KeyNotFoundFault`.
|
||||
|
||||
`ResizableMap<K,V>` étend `SettableMap<K,V>` et ajoute les changements structurels :
|
||||
|
||||
```text
|
||||
insert(K key, V value) -> Void
|
||||
faults DuplicateKeyFault
|
||||
|
||||
remove(const K key) -> Void
|
||||
faults KeyNotFoundFault
|
||||
|
||||
clear() -> uint64
|
||||
```
|
||||
|
||||
`insert` affirme que la clé est nouvelle ; `remove` affirme qu'elle existe. Leurs violations dynamiques sont des `Fault` unchecked et capturables.
|
||||
|
||||
Le Core ne fournit pas mécaniquement `tryInsert` / `tryRemove` ayant pour seule fonction de dupliquer ces opérations dans `Result` ou `bool`. Une variante conditionnelle ne sera ajoutée que si elle porte une sémantique réellement utile distincte.
|
||||
|
||||
Il n'existe pas de `put()` implicite « insert ou replace » tant qu'un besoin concret ne justifie pas cette troisième intention.
|
||||
|
||||
### 22.4.11 `MapEntry<K,V>`
|
||||
|
||||
`MapEntry<K,V>` représente une paire clé/valeur observée lors d'une projection `entries()`.
|
||||
|
||||
Conceptuellement :
|
||||
|
||||
```text
|
||||
struct MapEntry<K,V> {
|
||||
const method key() -> K;
|
||||
const method value() -> V;
|
||||
}
|
||||
```
|
||||
|
||||
`MapEntry` n'est pas un proxy mutable vers un bucket interne de la map et n'expose pas de `setValue()` implicite.
|
||||
|
||||
La mutation d'une map reste explicite via :
|
||||
|
||||
```text
|
||||
map[key] = value;
|
||||
```
|
||||
|
||||
La sémantique de copie/référence de `K` et `V` suit les règles normales de leurs types.
|
||||
|
||||
### 22.4.12 Ordre : `Ordering`, `Comparable<T>` et `Comparator<T>`
|
||||
|
||||
L'ordre total applicatif utilise :
|
||||
|
||||
```text
|
||||
enum Ordering {
|
||||
Less,
|
||||
Equal,
|
||||
Greater
|
||||
}
|
||||
```
|
||||
|
||||
`Comparable<T>` exprime l'ordre naturel ou principal du type dans son domaine :
|
||||
|
||||
```text
|
||||
interface Comparable<T> {
|
||||
const method compareTo(const T other) -> Ordering;
|
||||
}
|
||||
```
|
||||
|
||||
Un type peut tout à fait implémenter `Comparable<T>` tout en supportant plusieurs ordres alternatifs via des comparators. Par exemple, un `User` d'un jeu peut avoir un classement principal naturel et rester comparable autrement par nom, niveau ou date.
|
||||
|
||||
`Comparator<T>` exprime un ordre externe/alternatif :
|
||||
|
||||
```text
|
||||
interface Comparator<T> {
|
||||
const method compare(const T left, const T right) -> Ordering;
|
||||
}
|
||||
```
|
||||
|
||||
Règle de sélection :
|
||||
|
||||
```text
|
||||
Comparator explicitement fourni
|
||||
-> utilisé exclusivement
|
||||
|
||||
aucun Comparator fourni
|
||||
-> Comparable<T> requis
|
||||
```
|
||||
|
||||
Aucun mélange/fallback entre les deux n'est effectué pendant une même opération ou dans une même collection ordonnée.
|
||||
|
||||
`Ordering::Equal` signifie équivalence selon cette relation d'ordre. Il n'implique pas nécessairement `left == right`.
|
||||
|
||||
Les implémentations de `Comparable` et `Comparator` doivent respecter cohérence, symétrie d'ordre et transitivité. Le compilateur n'est pas tenu de prouver ces propriétés générales.
|
||||
|
||||
### 22.4.13 `SortedSet<T>` et `SortedMap<K,V>`
|
||||
|
||||
`SortedSet<T>` étend `Set<T>` et garantit un ordre total stable selon le comparator actif :
|
||||
|
||||
```text
|
||||
interface SortedSet<T> extends Set<T> {
|
||||
const method comparator() -> Option<Comparator<T>>;
|
||||
const method first() -> Option<T>;
|
||||
const method last() -> Option<T>;
|
||||
}
|
||||
```
|
||||
|
||||
`None` pour `comparator()` signifie que l'ordre naturel `Comparable<T>` est utilisé. `Some(comparator)` expose l'ordre externe choisi pour cette instance.
|
||||
|
||||
`SortedMap<K,V>` étend `Map<K,V>` et ordonne les entrées par clé :
|
||||
|
||||
```text
|
||||
interface SortedMap<K,V> extends Map<K,V> {
|
||||
const method comparator() -> Option<Comparator<K>>;
|
||||
const method firstKey() -> Option<K>;
|
||||
const method lastKey() -> Option<K>;
|
||||
}
|
||||
```
|
||||
|
||||
Pour une `SortedMap`, les vues `keys()`, `values()` et `entries()` parcourent les données dans l'ordre des clés.
|
||||
|
||||
Les opérations de bornes/ranges (`floor`, `ceiling`, `lower`, `higher` ou noms définitifs) seront fermées séparément afin de ne pas introduire de noms ambigus par simple imitation d'une autre plateforme.
|
||||
|
||||
### 22.4.14 `TreeSet<T>` et `TreeMap<K,V>`
|
||||
|
||||
Les types standard ordonnés généraux sont nommés :
|
||||
|
||||
```text
|
||||
TreeSet<T>
|
||||
TreeMap<K,V>
|
||||
```
|
||||
|
||||
Le nom n'impose pas une structure arborescente précise au niveau ABI/implémentation tant que le contrat observable reste respecté.
|
||||
|
||||
Un futur `BTreeMap<K,V>` peut exister comme implémentation explicitement fondée sur un B-tree ; il ne remplace pas le nom général `TreeMap`.
|
||||
|
||||
Comme Saselang n'autorise qu'un `construct` par classe, les deux modes de création passent par des factories de classe distinctes :
|
||||
|
||||
```text
|
||||
TreeSet<T>::natural()
|
||||
requiert T implements Comparable<T>
|
||||
|
||||
TreeSet<T>::withComparator(Comparator<T> comparator)
|
||||
n'exige pas Comparable<T>
|
||||
|
||||
TreeMap<K,V>::natural()
|
||||
requiert K implements Comparable<K>
|
||||
|
||||
TreeMap<K,V>::withComparator(Comparator<K> comparator)
|
||||
n'exige pas Comparable<K>
|
||||
```
|
||||
|
||||
Les contraintes appartiennent aux factories concernées et non nécessairement au type générique entier.
|
||||
|
||||
### 22.4.15 Contraintes des implémentations concrètes
|
||||
|
||||
Les interfaces abstraites `Set<T>` et `Map<K,V>` n'imposent pas une stratégie de stockage particulière.
|
||||
|
||||
Ainsi :
|
||||
|
||||
```text
|
||||
HashSet<T> / HashMap<K,V>
|
||||
peuvent exiger des capacités de hash/égalité
|
||||
|
||||
TreeSet<T> / TreeMap<K,V>
|
||||
utilisent Comparable ou Comparator
|
||||
```
|
||||
|
||||
`Hashable`, l'égalité et leurs contrats exacts seront fermés dans le bloc dédié. Ils ne sont pas imposés à `Set<T>` ou `Map<K,V>` eux-mêmes.
|
||||
|
||||
### 22.4.16 Collections concurrentes
|
||||
|
||||
Les garanties concurrentes sont orthogonales aux capacités structurelles et relèvent du SDK.
|
||||
|
||||
Une future :
|
||||
|
||||
```text
|
||||
ConcurrentMap<K,V>
|
||||
```
|
||||
|
||||
exprime des garanties de concurrence/atomicité et ne remplace pas `ResizableMap<K,V>`.
|
||||
|
||||
Un type concret peut par exemple implémenter les deux :
|
||||
|
||||
```text
|
||||
ConcurrentHashMap<K,V>
|
||||
implements ResizableMap<K,V>, ConcurrentMap<K,V>
|
||||
```
|
||||
|
||||
Le SDK n'introduit pas une variante `ConcurrentX` pour chaque type uniquement par symétrie. Les interfaces concurrentes ne sont ajoutées que lorsqu'un contrat atomique/concurrent concret existe.
|
||||
|
||||
Une opération composée n'est pas atomique simplement parce que chaque appel individuel est thread-safe. Les futures opérations atomiques (`putIfAbsent`, comparaison/remplacement, etc.) seront spécifiées avec le modèle de concurrence.
|
||||
|
||||
## 22.5 `Range<T>` — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
|
||||
@@ -308,7 +639,7 @@ valeur finie autorisée
|
||||
|
||||
Les bornes sont évaluées de gauche à droite, exactement une fois chacune, avant la construction du range.
|
||||
|
||||
Une borne statiquement prouvée invalide provoque une erreur de compilation. Une borne calculée dynamiquement mais invalide selon le contrat de `Range<T>` provoque un runtime fault lors de la construction directe. Une API Core explicite retournant `Result` pourra être fournie lorsqu'une validation récupérable est souhaitée.
|
||||
Une borne statiquement prouvée invalide provoque une erreur de compilation. Une borne calculée dynamiquement mais invalide selon le contrat de `Range<T>` provoque un `Fault` runtime lors de la construction directe. Le nom concret du fault sera fixé avec l'API Core ; aucune variante `try... -> Result` parallèle n'est créée automatiquement pour la même validation.
|
||||
|
||||
`lower > upper` ne constitue pas une erreur : le résultat est un range vide.
|
||||
|
||||
@@ -392,7 +723,7 @@ RangeStep<Date,Duration>
|
||||
|
||||
et de refuser des couples qui introduiraient une perte ou n'auraient pas de sens. Par exemple, un range `float16` peut recevoir seulement les types de pas explicitement supportés sans imposer qu'un `float32` plus large soit accepté.
|
||||
|
||||
Le pas exprime une magnitude de progression, pas une direction. Pour les types numériques Core, il doit être strictement supérieur à zéro. Un pas statiquement nul ou négatif est une erreur de compilation ; une valeur dynamique invalide provoque un runtime fault lors de la construction directe de la progression. Une API explicite en `Result` pourra exister pour une validation récupérable.
|
||||
Le pas exprime une magnitude de progression, pas une direction. Pour les types numériques Core, il doit être strictement supérieur à zéro. Un pas statiquement nul ou négatif est une erreur de compilation ; une valeur dynamique invalide provoque un `Fault` runtime lors de la construction directe de la progression. Aucune variante `try... -> Result` n'est ajoutée uniquement pour dupliquer ce contrôle.
|
||||
|
||||
Pour les types utilisateur, la validité du pas est définie par le contrat Range correspondant et n'est pas réduite artificiellement à une comparaison numérique avec zéro.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user