LEÇON 6 / 60 minutes

Décider et répéter

Les conditions choisissent un chemin ; les boucles répètent un travail. Ces outils transforment une suite d’instructions en un programme qui réagit aux données.

À retenir·Toute répétition doit avoir une progression visible et une condition d’arrêt que vous pouvez expliquer.

Choisir avec if

Une condition if exécute un bloc si son expression booléenne est vraie. else donne le chemin alternatif ; elif ajoute un autre test dans la même décision.

proc categorie(age: i64) -> i64 {
    if age < 0 {
        return -1;
    } elif age < 18 {
        return 0;
    } else {
        return 1;
    }
}

Lisez les branches dans l’ordre. La première condition vraie choisit un chemin, donc placez les tests spécifiques avant les cas plus généraux. Chaque branche ici renvoie aussitôt une valeur : on voit clairement qu’aucun cas ne doit se poursuivre vers les lignes suivantes.

Répéter avec while

Une boucle while vérifie sa condition avant chaque passage. Son corps doit normalement faire évoluer une donnée qui rapproche le programme de l’arrêt.

proc somme_de_un_a_cinq() -> i64 {
    let mut indice: i64 = 1;
    let mut total: i64 = 0;

    while indice <= 5 {
        set total = total + indice;
        set indice = indice + 1;
    }

    return total;
}

On commence avec indice = 1. À chaque passage, on ajoute l’indice au total et on l’augmente. Après le passage où l’indice vaut 5, il devient 6 ; la condition indice <= 5 est alors fausse et la procédure renvoie 15. Sans l’incrément, le programme resterait dans la boucle indéfiniment.

Exemple vérifié : while, continue et break

examples/tutorials/controle.vit saute l’indice 3, s’arrête à 6 et vérifie que le total est 12.

build/bin/vitte run examples/tutorials/controle.vit --quiet --no-color

Résultat confirmé : code de sortie 0.

Répétition ouverte et sortie anticipée

La grammaire prévoit aussi loop { ... }, une boucle sans condition placée en tête. Elle se termine généralement par break; lorsqu’un cas d’arrêt est atteint. continue; saute au début du prochain passage. Ces sauts peuvent être utiles, mais si plusieurs points quittent le corps, vérifiez que le flot de contrôle reste facile à suivre.

proc chercher_valeur() -> i64 {
    let mut essai: i64 = 0;
    loop {
        if essai == 7 {
            break;
        }
        set essai = essai + 1;
    }
    return essai;
}

Parcourir avec for

La forme for nom in expression { ... } exprime un parcours. Selon les types d’itérables et la bibliothèque disponibles, l’expression peut être une plage ou une séquence. L’exemple suivant montre l’intention d’une plage d’indices ; vérifiez la prise en charge de l’itération dans la version du compilateur que vous utilisez.

proc additionner_cinq(valeurs: [5]i64) -> i64 {
    let mut total: i64 = 0;
    for index in 0..5 {
        set total = total + valeurs[index];
    }
    return total;
}

La plage 0..5 contient les indices 0 à 4 : la borne finale est exclue. Cette convention est pratique pour parcourir un tableau de cinq éléments. Le parcours par plage est utile quand vous avez besoin de l’indice ; si une collection fournit un itérateur et que votre code n’a pas besoin de position, l’itérateur peut exprimer l’intention plus directement.

État de vérification de for

Les tests du dépôt n’ont pas confirmé l’exécution de la forme for sur plage. Le test ciblé d’un for sur tableau atteint puis échoue au backend. Pour un parcours exécutable avec le compilateur natif audité, utilisez l’exemple while ci-dessus.

Choisir un cas avec match

match associe une expression à plusieurs bras. Dans la grammaire, chaque bras utilise => et se termine par une virgule. Avec une énumération déclarée par pick, cette forme rend les différents états visibles ensemble. La couverture d’exhaustivité dépend de l’analyseur et du compilateur ; traitez chaque cas important explicitement.

pick Etat {
    Inactif,
    Pret,
    Termine,
}

proc code_etat(etat: Etat) -> i64 {
    match etat {
        Etat.Inactif => { return 0; },
        Etat.Pret => { return 1; },
        Etat.Termine => { return 2; },
    }
    return -1;
}

Pour les erreurs de compilation liées à une branche, commencez par vérifier le type de l’expression examinée, puis la syntaxe de chaque bras et ses séparateurs.

Trois garanties pour une boucle maîtrisée

  • La valeur d’état qui change à chaque passage est identifiable.
  • La condition d’arrêt finit par être atteinte ou un break explicite termine le parcours.
  • Le comportement aux limites — zéro élément, un seul élément et valeur maximale — est défini.
Table de progression

Une table avec l’indice, l’état et le total rend visibles les bornes décalées et les mises à jour oubliées. Pour la boucle présentée ici, les valeurs successives du total apparaissent dans le tableau qui suit.

Transformer une décision en table de cas

Une table de cas rend l’ordre des branches de categorie(age) explicite :

EntréePremière condition vraieRésultat
age < 0age < 0-1
0 <= age < 18age < 180
age >= 18else1

Cette table montre pourquoi l’ordre des tests compte. Si age < 18 passait en premier, les âges négatifs recevraient le résultat de la deuxième catégorie. Une analyse des décisions gagne à inclure les valeurs juste avant et juste après chaque frontière.

Tracer une boucle avant de l’exécuter

Pour la boucle qui additionne de 1 à 5, l’état au début des passages est :

indicetotal avanttotal après
101
213
336
4610
51015

Après le dernier passage, l’indice devient 6 et indice <= 5 est faux. Si vous changez la condition en indice < 5 sans changer l’initialisation, la valeur 5 n’est plus ajoutée : le total devient 10. Une trace courte rend visible cet effet immédiatement.

Comprendre break et continue dans l’ordre

Dans controle.vit, l’indice progresse avant les deux décisions. À 3, continue saute le reste du corps et le total ne change pas. À 6, break quitte la boucle avant l’addition. L’ordre des lignes définit donc quels nombres participent au total. Déplacer l’incrément après un continue pourrait empêcher l’indice de progresser et créer une boucle sans fin.

Un match est une autre manière d’exprimer des cas nommés. Il convient surtout lorsque la donnée représente une variante d’un type pick. N’utilisez pas plusieurs comparaisons numériques lorsqu’un état nommé décrit mieux ce que le programme examine.

Progression recommandée pour le compilateur actuel

Apprenez d’abord if, while, les mises à jour set et les tableaux fixes : ces éléments ont des exemples exécutés. Étudiez for comme une syntaxe Vitte décrite, mais ne dépendez pas de son exécution sans preuve correspondante dans la version utilisée.

Une condition définit un graphe de chemins

Une suite de if, elif et else représente un choix ordonné. Le programme évalue les conditions selon l’ordre écrit ; dès qu’une condition est vraie, le bloc correspondant est exécuté et les autres branches de la même décision ne le sont pas. Les frontières entre catégories doivent donc être cohérentes. Dans categorie, le test age < 0 précède age < 18 afin que les valeurs négatives ne soient pas classées comme mineures.

Quand chaque branche renvoie une valeur, la relation entre le cas et le résultat est locale. Quand une branche modifie une variable puis rejoint le flot commun, il faut suivre cet état jusqu’aux lignes suivantes. Les conditions imbriquées créent plusieurs chemins ; des retours anticipés ou un match sur un type pick peuvent rendre les cas plus lisibles lorsqu’ils représentent des états nommés.

Une boucle est un état qui évolue

La boucle while teste sa condition avant d’exécuter son corps. Dans la somme de 1 à 5, l’état est le couple (indice, total). Au départ, il vaut (1, 0). Un passage ajoute l’indice au total et augmente l’indice. Après le passage avec l’indice 5, l’état devient (6, 15) ; la condition est alors fausse et le programme sort. Cette transition décrit le comportement plus précisément que « la boucle compte jusqu’à cinq ».

Les instructions continue et break modifient ce trajet. continue abandonne le reste du corps et revient au test ; toute progression indispensable doit donc avoir lieu sur ce chemin également. break quitte immédiatement la boucle, ce qui crée une condition de sortie supplémentaire. L’exemple vérifié montre que l’ordre de l’incrément, du test de saut et de l’arrêt influe directement sur les valeurs ajoutées.

Choisir entre while, loop, for et match

while convient à une répétition dont la condition est connue à chaque entrée dans le corps ; loop exprime une répétition ouverte interrompue par une sortie explicite ; for exprime un parcours d’éléments ou d’une plage. Ces formes ne sont pas interchangeables au niveau de la lisibilité, même si elles peuvent décrire des parcours similaires. Dans le dépôt audité, la syntaxe de for est reconnue à certaines étapes, mais l’exécution sur tableau atteint un rejet backend ; while possède des exemples exécutés.

match est particulièrement utile lorsque l’expression représente une variante d’un pick. Chaque bras associe une variante à son traitement, éventuellement avec une charge utile. L’exhaustivité et les formes avancées restent à vérifier selon le compilateur. La sélection par noms d’état complète ainsi les décisions numériques exprimées par if, tout en gardant visible la différence entre une construction décrite et une construction exécutée.

Brancher sur une valeur plutôt que disperser les tests

Une décision composée de comparaisons convient à des plages numériques et des conditions booléennes. Un match sur un type pick convient quand les cas ont des noms : état inactif, état prêt ou état terminé. Les bras rassemblent les traitements au même endroit. Le type exprime la catégorie de la valeur, et la structure de contrôle exprime la réponse du programme.

Dans la grammaire, un bras suit la forme d’un motif, d’une flèche => et d’une expression ou d’un bloc. Les virgules séparent les bras. L’outil peut accepter cette structure syntaxiquement sans démontrer que tous les cas sont couverts ou que chaque corps renvoie le type annoncé. Les erreurs de branche se situent donc potentiellement au parsing, à l’analyse sémantique ou à une étape ultérieure.

Lire une boucle à travers ses frontières

Pour un tableau, la frontière haute est la longueur, et non le dernier indice valide. Si la longueur vaut cinq, les indices vont de zéro à quatre. Pour une boucle qui additionne de 1 à 5, la frontière de la condition inclut au contraire la valeur 5. Il faut donc choisir < ou <= à partir de la signification de la borne et de l’initialisation, pas par habitude.

Une boucle while exécute le corps zéro fois ou davantage, selon la condition initiale et les mises à jour. Une boucle loop exécute son corps au moins une fois, sauf si un branchement la quitte immédiatement. Ce nombre minimal de passages change la manière de gérer un tableau vide et un résultat initialisé. Ces propriétés algorithmiques sont indépendantes du statut de support de for au backend.