2016-01-22 7 views
7

mam tego typu ENUM:Unwrap typ enum wariant wewnętrzny, gdy znany jest

enum Animal { 
    Dog(i32), 
    Cat(u8), 
} 

Teraz mam funkcję, która pobiera jako parametr tego typu. I wiem (z jakiegoś powodu), że dane wejściowe są zawsze Cat. Chcę to osiągnąć:

fn count_legs_of_cat(animal: Animal) -> u8 { 
    if let Animal::Cat(c) = animal { c } else { unreachable!() } 
} 

Czy mogę napisać krótszy i/lub bardziej idiomatyczny?

Odpowiedz

11

Niezupełnie. Co widziałem jest wprowadzenie nowego struct dla każdego wariantu enum, a następnie sposoby na wyliczenia, aby go rozkładać:

struct Dog(i32); 
struct Cat(u8); 

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

impl Animal { 
    fn cat(self) -> Cat { 
     if let Animal::Cat(c) = self { c } else { panic!("Not a cat") } 
    } 

    fn dog(self) -> Dog { 
     if let Animal::Dog(d) = self { d } else { panic!("Not a dog") } 
    } 
} 

// Or better an impl on `Cat` ? 
fn count_legs_of_cat(c: Cat) -> u8 { 
    c.0 
} 

oczywiście, nie potrzebę struct a może po prostu zwrócić u8 , ale może to być trudne do śledzenia.

Jednak w przyszłości jest jeszcze lepsze wsparcie. I Myślę, że to "efficient code reuse" RFC, ale lepiej opisane w blogu Virtual Structs Part 3: Bringing Enums and Structs Together. Propozycja polegałaby na tym, aby Animal::Cat był samodzielnym typem, a zatem Twoja metoda mogłaby zaakceptować numer Animal::Cat i nie musieć się o to martwić.


Osobiście prawie zawsze wolą napisać kod w mojej wrodzonej nieomylną realizację i zmusić rozmówcę do paniki:

impl Animal { 
    fn cat(self) -> Option<Cat> { 
     if let Animal::Cat(c) = self { 
      Some(c) 
     } else { 
      None 
     } 
    } 

    fn dog(self) -> Option<Dog> { 
     if let Animal::Dog(d) = self { 
      Some(d) 
     } else { 
      None 
     } 
    } 
} 

A ja prawdopodobnie użyć match

impl Animal { 
    fn cat(self) -> Option<Cat> { 
     match self { 
      Animal::Cat(c) => Some(c), 
      _ => None, 
     } 
    } 

    fn dog(self) -> Option<Dog> { 
     match self { 
      Animal::Dog(d) => Some(d), 
      _ => None, 
     } 
    } 
} 
+2

zamiast implantów Zwierząt mam tendencję do implikowania cechy Into, jak [ten przykład placu zabaw] (http://is.gd/jmS3RB). Z prostymi wyliczeniami powinno być względnie łatwo mieć makro, które generuje importy, ale nie jest to wzór, którego używam tak bardzo, więc nigdy nie napisałem tego dookoła ... –

Powiązane problemy