Aller au contenu
Français

Guide du langage

Cette documentation décrit le périmètre figé de la préversion expérimentale v0.0.18. La publication effective et les téléchargements sont consignés dans GitHub Releases. Ce guide présente la syntaxe essentielle. Le contrat syntaxique et le contrat sémantique du dépôt restent les références faisant autorité. Ces fragments sont pédagogiques ; consultez la prise en charge des backends pour les différences.

name = "Ku"
count:int = 3
ready:bool = true
values:[int] = [1, 2, 3]
count += 1

La première affectation déclare une variable. Les types primitifs sont int, float, bool, str et null. Les entiers sont signés sur 64 bits ; les flottants utilisent binary64. Les entiers ne deviennent pas des conditions par conversion implicite en valeur vraie.

Cet exemple élémentaire complet provient de examples/function.ku :

fn add(a: int, b: int): int {
return a + b
}
fn main() {
println(add(10, 20))
}

Sortie attendue : 30. Ce fragment de contrôle peut être placé dans main :

total = 0
for i in 5 {
total += i
}
if (total == 10) {
println("sum ok")
}

for i in 5 parcourt les valeurs de 0 à 4. if et while exigent des conditions de type bool. Utilisez des accolades pour plusieurs instructions. Les expressions de branchement utilisent match ; il n’existe pas de switch.

int, float, bool et null sont des valeurs Copy. Les chaînes, tableaux, objets, structs, enums, Results et valeurs de fonction sont Owned. Les affectations et les arguments ordinaires déplacent les valeurs possédées par défaut. Utilisez .clone() pour obtenir une valeur indépendante. Les Tasks ne peuvent pas être clonées.

original = "Ku"
copy = original.clone()
println(original)
println(copy)

Une fonction synchrone peut déclarer un paramètre emprunté en lecture seule :

fn length(&text: str): int {
return text.len()
}

Appelez-la sous la forme length(value), sans & sur l’argument. Les données empruntées ne peuvent être modifiées, déplacées hors de l’emprunt ni s’échapper de l’appel. Les combinaisons telles que les paramètres async empruntés restent non prises en charge. L’emprunt en lecture seule ne garantit pas la pureté de toute fonction.

struct User {
name: str
age: int
}
user = User { name: "Ku", age: 1 }
println(user.name)

Les objets dynamiques utilisent { name: "Ku" }. Un accès ordinaire à un index d’objet absent échoue. value["name"]? effectue la recherche via Result et fournit un KuValue en cas de réussite. Utilisez .as_str()? ou .as_int()? pour obtenir un type concret. Une clé absente ne devient pas silencieusement null.

Les importations de la bibliothèque standard utilisent des chemins à points, comme import json from "std.json". Les modules locaux peuvent utiliser import math from "./math". Les exportations de premier niveau définies par l’utilisateur commencent par une majuscule ASCII ; les noms en minuscules restent privés au fichier.

Le type de retour T! peut renvoyer T ou Error. ? propage une erreur récupérable ; fail en crée une :

fn read_name(): str! {
fail "name missing"
}
fn main() {
try {
println(read_name()?)
} catch (error) {
println(error.message)
}
}

Error possède les champs domain, code et message. Un catch ordinaire n’intercepte ni panic, ni l’annulation de Task, ni l’expiration d’un délai. Le nettoyage d’annulation dans finally partage un budget à échéance absolue ; il ne garantit pas l’achèvement de n’importe quel nettoyage utilisateur.

Le code applicatif obtient un handle Task à usage unique en appelant une async fn, puis utilise await. Il n’existe aucune API applicative nommée task.spawn, Task.new ou thread.spawn. L’interpréteur et le sous-ensemble natif Task ont des couvertures différentes. Un exemple fonctionnant sur un backend ne prouve pas la prise en charge complète sur un autre. Voir la prise en charge des plateformes et backends.