Je veux appliquer filter
sur un itérateur et je suis venu avec celui-ci et cela fonctionne, mais il est super verbeux:
.filter(|ref my_struct| match my_struct.my_enum { Unknown => false, _ => true })
Je préfère écrire quelque chose comme ceci:
.filter(|ref my_struct| my_struct.my_enum != Unknown)
Cela me donne une erreur de compilation
binary operation `!=` cannot be applied to type `MyEnum`
Existe-t-il une alternative à la correspondance de motifs verbeux? J'ai cherché une macro mais je n'ai pas trouvé de macro appropriée.
Tout d'abord, vous pouvez utiliser le trait PartialEq
, par exemple, par #[derive]
:
#[derive(PartialEq)]
enum MyEnum { ... }
Ensuite, votre variante "idéale" fonctionnera telle quelle. Cependant, cela nécessite que le contenu de MyEnum
implémente également PartialEq
, ce qui n'est pas toujours possible/souhaité.
Deuxièmement, vous pouvez implémenter une macro vous-même, quelque chose comme ça (bien que cette macro ne prenne pas en charge toutes sortes de modèles, par exemple, des alternatives):
macro_rules! matches(
($e:expr, $p:pat) => (
match $e {
$p => true,
_ => false
}
)
)
Ensuite, vous l'utiliseriez comme ceci:
.filter(|ref my_struct| !matches!(my_struct.my_enum, Unknown))
Il y a n RFC pour ajouter une telle macro dans la bibliothèque standard, mais elle est toujours en discussion.
J'utiliserais la correspondance de motifs, mais je la déplacerais vers une méthode sur l'énumération afin que la fermeture du filtre soit plus ordonnée:
#[derive(Debug)]
enum Thing {
One(i32),
Two(String),
Unknown,
}
impl Thing {
fn is_unknown(&self) -> bool {
match *self {
Thing::Unknown => true,
_ => false,
}
}
}
fn main() {
let things = vec![Thing::One(42), Thing::Two("hello".into()), Thing::Unknown];
for t in things.iter().filter(|s| !s.is_unknown()) {
println!("{:?}", t);
}
}
Voir également:
Vous pouvez utiliser if let Some(x) = option { then }
idiome avec le même if let
construire mais sans déstructurer:
if let Unknown = my_struct.my_enum { false } else { true }