Pourquoi «break» n'a-t-il pas besoin d'un point-virgule pour terminer une «boucle»?

Nov 26 2020

Extrait du chapitre 3.5 du livre de rouille:

... nous utilisons le breakmot - clé avec la valeur counter * 2. Après la boucle, nous utilisons un point-virgule pour terminer l'instruction qui attribue la valeur à result.

Plus l'extrait de code:

fn main() {
    let mut counter = 0;

    let result = loop {
        counter += 1;

        if counter == 10 {
            break counter * 2;
        }
    };

    println!("The result is {}", result);
}

Je comprends comment cela fonctionne et pourquoi le résultat est 20, mais j'ai remarqué que si je supprime le point-virgule sur la ligne qui contient le mot-clé "break", le programme est équivalent.

Pourquoi le point-virgule est-il facultatif dans ce cas?

Réponses

5 E_net4thecurator Nov 26 2020 at 22:30

Un exemple plus court:

let _: i32 = loop {
    if true {
        break 3; // ()
    }
};

C'est juste un autre exemple où le point-virgule n'interfère pas avec le résultat attendu. D'une part, l'insertion d'un point-virgule introduit une instruction d'expression, qui correspond au type d'unité (). Comme les expressions loops et ifcontinuent d'admettre un bloc de code évaluant le même type (), tous les types sont conformes.

let _: i32 = loop {
    if true {
        break 3 // !
    }
};

Si le point-virgule est supprimé, le breakest évalué sur le type! Never, qui contraint à tout autre type. Cela signifie qu'il remplira tout type attendu par la portée externe. Donc tout va bien tout de même, tant que vous n'essayez pas d'ajouter une autre instruction avant la fin du bloc if.

Les deux breaket returnévaluer !, car leurs effets secondaires impliquent que le programme ne se déroulera pas avec le flux de travail naturel.

Voir également:

  • Pourquoi les expressions de retour utilisent-elles des points-virgules lorsqu'elles sont inutiles?
  • Quelle est la différence entre l'utilisation de l'instruction return et l'omission du point-virgule dans Rust?
  • Comment affirmer statiquement que la fin d'une fonction est inaccessible
3 pretzelhammer Nov 26 2020 at 22:42

La référence du langage Rust sur les instructions d'expression :

Une instruction d'expression est celle qui évalue une expression et ignore son résultat. En règle générale, le but d'une instruction d'expression est de déclencher les effets de l'évaluation de son expression.

Une expression qui consiste uniquement en une expression de bloc ou une expression de flux de contrôle, si elle est utilisée dans un contexte où une instruction est autorisée, peut omettre le point-virgule de fin .

J'imagine que c'est purement pour l'esthétique et l'ergonomie, puisque presque tout est une expression dans Rust. Si le point-virgule de fin était obligatoire après toutes les expressions, nous devrons terminer les blocs if-else (qui sont également des expressions) par des points-virgules, ce qui semble terrible:

if {
    // do something
} else {
    // do something else
}; // <- gross

De même, nous pouvons omettre le point-virgule de fin sur toutes les expressions de flux de contrôle car elles produisent un flux de contrôle, de sorte que la fonction typique du point-virgule, qui consiste à ignorer le résultat de l'expression et à évaluer à la ()place, devient non pertinente.

fn five() -> i32 {
    return 5 // to semicolon or not to semicolon? it doesn't matter
}

Dans l'exemple ci-dessus, cela ne fait aucune différence si nous nous terminons return 5par un point-virgule ou non puisque rien ne peut de toute façon «capturer» le résultat de cette expression puisqu'elle produit un flux de contrôle. Il en serait de même pour d'autres expressions de flux de contrôle telles que breaket continue.