J'apprends Rust et je suis tombé sur le fait que l'ajout d'un trait de soulignement au début d'un nom de variable ne fera pas avertir le compilateur s'il n'est pas utilisé. Je me demande pourquoi cette fonctionnalité existe, car les variables inutilisées sont désapprouvées.
Je peux voir plusieurs raisons:
#[must_use]
type, mais dans votre cas particulier, vous savez que vous pouvez ignorer la valeur en toute sécurité. Il est possible d'utiliser un _
modèle pour cela (qui n'est pas une liaison de variable, c'est un modèle qui lui est propre, mais c'est probablement d'où vient la convention de préfixe de soulignement), mais vous voudrez peut-être documenter pourquoi vous ignorez la valeur, ou quelle est cette valeur . C'est particulièrement courant dans les tests d'après mon expérience.used_underscore_binding
charpie._
pour ce cas d'utilisation, comme _
n'est pas une liaison de variable et la valeur serait supprimée à la fin de l'instruction.Voici quelques exemples des raisons pour lesquelles vous souhaiterez peut-être ignorer une variable inutilisée. Considérez _s
Dans la fonction suivante.
fn add_numbers(f: i32, _s: i32) -> i32 {
f + 1
}
La variable _s
Permet de conserver la même signature même si nous ne l'avons pas implémentée. Cela fonctionne également si nous avons découvert que nous n'avions pas besoin du _s
Mais parce que notre bibliothèque est utilisée dans de nombreux projets différents, nous ne voulions pas changer l'API pour notre fonction. Cela peut ou non être une mauvaise pratique, mais pourrait être utile dans une situation où _s
Doit rester et ne rien faire. Nous pourrions également utiliser _
Ici, mais _s
A potentiellement plus de sens quant à la finalité de la variable.
L'endroit suivant où cela peut être utile est lorsqu'un type implémente Drop
et que vous vous souciez de l'emplacement de cette logique. Dans cet exemple, vous pouvez voir que la variable _result
Est nécessaire pour que Drop
se produise à la fin.
fn main() {
let mut num = 1;
// let _ = try_add_numbers(&mut num); // Drop is called here for _
let _result = try_add_numbers(&mut num); // without the _result we have a warning.
println!("{}", num);
// Drop is called here for the _result
}
// keep the api the same even if an aurgument isn't needed anymore or
// has not been used yet.
fn add_numbers(f: i32, _s: i32) -> i32 {
f + 1
}
// This function returns a result
fn try_add_numbers(i: &mut i32) -> Result<GoodResult, GoodResult> {
if *i > 3 {
return Err(GoodResult(false));
}
*i = add_numbers(*i, 0);
Ok(GoodResult(true))
}
struct GoodResult(bool);
impl Drop for GoodResult {
fn drop(&mut self) {
let &mut GoodResult(result) = self;
if result {
println!("It worked");
} else {
println!("It failed");
}
}
}
Si nous utilisons let _result = try_add_numbers(&mut num);
nous avons une variable qui est dans la portée jusqu'à ce que la fin de main et drop soit appelée. Si nous avions utilisé let _ = try_add_numbers(&mut num);
nous n'avons toujours pas d'avertissement mais drop est appelé à la fin de l'instruction. Si nous utilisons try_add_numbers(&mut num);
sans liaison let, nous obtenons un avertissement. La sortie de ce programme change en fonction de celle que nous utilisons avec notre fonction try_add_numbers.
It worked
2
ou
2
It worked
Il y a donc une utilisation pour les variables _
Et _named
Qui doivent être choisies en fonction de la sortie de vos programmes. Jouez avec mon exemple sur le terrain de je pour vous en faire une idée.
Je suis tombé ici via Google en recherchant cet avertissement lié aux variables de correspondance. Ceci est tangentiellement lié.
Parfois, vous pouvez avoir du code où vous obtenez un Result
et souhaitez faire correspondre les cas, mais vous ne vous souciez pas de la valeur d'erreur. À la place d'utiliser _e
ou quelque chose, vous pouvez simplement utiliser _
qui ne lie pas explicitement. Voici un exemple concret. Nous ne nous soucions pas de la valeur de l'erreur car nous retournons la nôtre.
fn some_method() -> Result<u32, MyCustomError> {
// ...
let id: u32 = match some_str.parse() {
Ok(value) => value,
Err(_) => return Err(MyCustomError::Blah)
}
// ...
}