Je suis en train de lire la documentation pour File
:
//..
let mut file = File::create("foo.txt")?;
//..
Quel est le ?
dans cette ligne ? Je ne me souviens pas l'avoir vu dans le Livre de la rouille auparavant.
Je suis en train de lire la documentation pour File
:
//..
let mut file = File::create("foo.txt")?;
//..
Quel est le ?
dans cette ligne ? Je ne me souviens pas l'avoir vu dans le Livre de la rouille auparavant.
Comme vous l'avez peut-être remarqué, Rust n'a pas d'exceptions. Il a des paniques, mais leur utilisation pour la gestion des erreurs est déconseillée (elles sont destinées aux erreurs irrécupérables).
En Rust, la gestion des erreurs utilise Result
. Un exemple typique serait :
fn halves_if_even(i: i32) -> Result<i32, Error> {
if i % 2 == 0 {
Ok(i / 2)
} else {
Err(/* something */)
}
}
fn do_the_thing(i: i32) -> Result<i32, Error> {
let i = match halves_if_even(i) {
Ok(i) => i,
Err(e) => return Err(e),
};
// use `i`
}
C'est génial parce que :
Il est cependant loin d'être idéal, car il est très verbeux. C'est là que l'opérateur point d'interrogation ?
vient.
Ce qui précède peut être réécrit comme suit :
fn do_the_thing(i: i32) -> Result<i32, Error> {
let i = halves_if_even(i)?;
// use `i`
}
qui est beaucoup plus concise.
Quoi ?
fait ici est équivalente à la match
l'énoncé ci-dessus avec un ajout. En bref :
Result
si OKInto::into
sur la valeur de l'erreur pour éventuellement la convertir en un autre type.C'est un peu magique, mais la gestion des erreurs a besoin d'un peu de magie pour réduire le texte passe-partout, et contrairement aux exceptions, il est immédiatement visible quels appels de fonction peuvent ou ne peuvent pas se tromper : ceux qui sont ornés de ?
.
Un exemple de la magie est que cela fonctionne également pour Option
:
// Assume
// fn halves_if_even(i: i32) -> Option<i32>
fn do_the_thing(i: i32) -> Option<i32> {
let i = halves_if_even(i)?;
// use `i`
}
El ?
opérateur, stabilisé dans la version Rust 1.13.0 est alimenté par le (instable) Try
trait.
Voir aussi :
Il serait bien que vous étendiez un peu votre réponse, par exemple en expliquant que le type de retour de la fonction doit correspondre au type que vous essayez de "déballer", par exemple Result
o Option
.
En ce qui concerne les paniques transportant des informations structurées, elles le peuvent désormais grâce à panic_any
.
C'est pour la propagation d'erreur pour le type d'erreur récupérable Result<T, E>
. Il déballe le résultat et vous donne la valeur intérieure.
Plutôt que de traiter le cas d'erreur, vous le propagez au code de l'appelant et ne traitez que le Ok
cas. L'avantage est qu'il élimine une grande partie du texte passe-partout et rend l'implémentation de la fonction plus simple.
Il est utilisé pour propagating errors
. Parfois, nous écrivons du code qui peut échouer mais nous ne voulons pas attraper et traiter l'erreur immédiatement. Votre code ne sera pas lisible si vous avez trop de code pour traiter l'erreur à chaque endroit. Au lieu de cela, si une erreur se produit, nous pouvons vouloir laisser notre appelant s'en occuper. Nous voulons que les erreurs se propagent dans la pile d'appel.
let mut file = File::create("foo.txt")?;
Le comportement de ?
dépend du fait que cette fonction renvoie un résultat réussi ou un résultat d'erreur :
Utilisation de ?
comme ce code
let mut file = match File::create("foo.txt") {
Err(why) => panic!("couldn't create {}: {}", display, why),
Ok(file) => file,
};
?
fonctionne également de manière similaire avec le type Option. Dans une fonction qui renvoie Option, vous pouvez utiliser ? pour déballer une valeur et la retourner au début dans le cas de None :
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.
2 votes
Notez que la description de ? a été incluse dans le livre 2018. doc.rust-lang.org/edition-guide/rust-2018/