9 votes

Sortie d'une expression en bloc ? (similaire à la fonction "return")

On peut revenir d'une fonction avant d'atteindre la dernière instruction en utilisant "return", par exemple :

fn example() -> i32 {
    if true {
        return 1;
    }

    0 // this line is never reached
}

Est-il possible de faire quelque chose de similaire avec des expressions de bloc ? Exemple :

let foo = {
    if true {
        *something to exit with 1*
    }

    0 // this line is never reached
};

Merci pour toute aide.

P.S. Je sais que dans cet exemple simple, j'aurais pu utiliser l'expression "if-else". Je m'interroge sur les expressions de bloc en général, pas sur cet exemple en particulier :)

10voto

mcarton Points 5694

Pour Rust stable, il existe une " loop hack" :

fn main() {
    let foo = loop {
        if true {
            break 1;
        }

        break 0;
    };
}

Pour la nuit, il y a une caractéristique instable label_break_value qui fait exactement cela :

#![feature(label_break_value)]

fn main() {
    let foo = 'bar: {
        if true {
            break 'bar 1;
        }

        0 // this line is never reached
    };
}

Il ne semble pas évident, en regardant les problèmes de Github, que cette fonctionnalité sera un jour stabilisée. Elle a été implémentée pendant plus de deux ans, mais elle ne semble pas avoir suffisamment de partisans pour aller de l'avant.

8voto

justinas Points 2474

Vous pouvez également utiliser une fermeture immédiatement invoquée.

fn main() {
    let foo = (|| {
        if true {
            return 1;
        }

        0
    })();
}

Je parie que LLVM est assez intelligent pour optimiser l'appel de fonction dans les builds.

5voto

sebpuetz Points 1480

Je ne pense pas que ce soit possible actuellement mais j'ai trouvé ce problème de suivi : https://github.com/rust-lang/rust/issues/48594

5voto

kmdreko Points 3321

Non, il n'existe pas de mécanisme permettant de céder prématurément un bloc.

Il est intéressant de noter que ce mécanisme a été proposée . Tenter de le faire avec le break -label (utilisée dans les boucles) entraînera l'erreur :

let foo = 'a: {
    if true {
        break 'a 1;
    }
    0
};

error[E0658]: labels on blocks are unstable
 --> src/main.rs:2:13
  |
2 |     let s = 'a: {
  |             ^^
  |
  = note: see issue #48594 <https://github.com/rust-lang/rust/issues/48594> for more information

Donc cela fonctionnera sur le nocturne compilateur avec #![feature(label_break_value)] . Cependant, il ne faut pas s'attendre à ce que la situation se stabilise de sitôt.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X