web-dev-qa-db-fra.com

Quelle est la syntaxe à associer à une référence à une énumération?

Il semble que chaque document d'introduction pour les types d'énumération de Rust explique comment correspondre sur un objet d'énum que vous possédez , mais que se passe-t-il si vous ne possédez pas l'objet enum et que vous avez juste une référence à laquelle vous souhaitez faire correspondre? Je ne sais pas quelle serait la syntaxe.

Voici un code où j'essaie de faire correspondre une référence à une énumération:

use std::fmt;
use std::io::prelude::*;

pub enum Animal {
    Cat(String),
    Dog,
}

impl fmt::Display for Animal {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Animal::Cat(c) => f.write_str("c"),
            Animal::Dog => f.write_str("d"),
        }
    }
}

fn main() {
    let p: Animal = Animal::Cat("whiskers".to_owned());
    println!("{}", p);
}

Le Rust Playground donne des erreurs sur les deux premiers cas du match en essayant de le compiler:

error[E0308]: mismatched types
  --> src/main.rs:12:13
   |
12 |             Animal::Cat(c) => f.write_str("c"),
   |             ^^^^^^^^^^^^^^ expected &Animal, found enum `Animal`
   |
   = note: expected type `&Animal`
   = note:    found type `Animal`

error[E0308]: mismatched types
  --> src/main.rs:13:13
   |
13 |             Animal::Dog => f.write_str("d"),
   |             ^^^^^^^^^^^ expected &Animal, found enum `Animal`
   |
   = note: expected type `&Animal`
   = note:    found type `Animal`

Comment puis-je changer ce code pour le compiler? J'ai essayé d'ajouter des esperluettes dans beaucoup d'endroits différents sans aucune chance. Est-il même possible de faire correspondre une référence à une énumération?

28
David Grayson

À partir de Rust 1.26, la façon idiomatique est la façon dont vous l'avez écrit à l'origine parce que match l'ergonomie a été améliorée :

use std::fmt;

pub enum Animal {
    Cat(String),
    Dog,
}

impl fmt::Display for Animal {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Animal::Cat(_) => f.write_str("c"),
            Animal::Dog => f.write_str("d"),
        }
    }
}

fn main() {
    let p: Animal = Animal::Cat("whiskers".to_owned());
    println!("{}", p);
}
14
Shepmaster

La façon idiomatique serait

match *self {
    Animal::Cat(ref c) => f.write_str("c"),
    Animal::Dog => f.write_str("d"),
}

Vous pouvez utiliser _ au lieu de ref c pour désactiver l'avertissement "inutilisé".

23
WiSaGaN

Je l'ai compris grâce aux messages utiles du compilateur:

match self {
    &Animal::Cat(ref c) => f.write_str("c"),
    &Animal::Dog => f.write_str("d"),
}
11
David Grayson