# Enum 1. 🌟🌟 Enums can be created with explicit discriminator. ```rust,editable // fix the errors enum Number { Zero, One, Two, } enum Number1 { Zero = 0, One, Two, } // C-like enum enum Number2 { Zero = 0.0, One = 1.0, Two = 2.0, } fn main() { // a enum variant can be converted to a integer by `as` assert_eq!(Number::One, Number1::One); assert_eq!(Number1::One, Number2::One); println!("Success!") } ``` 2. 🌟 each enum variant can hold its own data. ```rust,editable // fill in the blank enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), } fn main() { let msg1 = Message::Move{__}; // instantiating with x = 1, y = 2 let msg2 = Message::Write(__); // instantiating with "hello, world!" println!("Success!") } ``` 3. 🌟🌟 we can get the data which a enum variant is holding by pattern match ```rust,editable // fill in the blank and fix the error enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), } fn main() { let msg = Message::Move{x: 1, y: 2}; if let Message::Move{__} = msg { assert_eq!(a, b); } else { panic!("NEVER LET THIS RUN!"); } println!("Success!") } ``` 4. 🌟🌟 ```rust,editable // fill in the blank and fix the errors enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), } fn main() { let msgs: __ = [ Message::Quit, Message::Move{x:1, y:3}, Message::ChangeColor(255,255,0) ]; for msg in msgs { show_message(msg) } } fn show_message(msg: Message) { println!("{}", msg); } ``` 5. 🌟🌟 As there is no `null` in Rust, we have to use enum `Option` to deal the cases when value is absent. ```rust,editable // fill in the blank to make the `println` work. // also add some code to prevent the `panic` from running. fn main() { let five = Some(5); let six = plus_one(five); let none = plus_one(None); if let __ = six { println!("{}", n); println!("Success!") } panic!("NEVER LET THIS RUN!"); } fn plus_one(x: Option) -> Option { match x { __ => None, __ => Some(i + 1), } } ``` 6. 🌟🌟🌟🌟 implement a `linked-list` via enums. ```rust,editable use crate::List::*; enum List { // Cons: Tuple struct that wraps an element and a pointer to the next node Cons(u32, Box), // Nil: A node that signifies the end of the linked list Nil, } // Methods can be attached to an enum impl List { // Create an empty list fn new() -> List { // `Nil` has type `List` Nil } // Consume a list, and return the same list with a new element at its front fn prepend(self, elem: u32) -> __ { // `Cons` also has type List Cons(elem, Box::new(self)) } // Return the length of the list fn len(&self) -> u32 { // `self` has to be matched, because the behavior of this method // depends on the variant of `self` // `self` has type `&List`, and `*self` has type `List`, matching on a // concrete type `T` is preferred over a match on a reference `&T` // after Rust 2018 you can use self here and tail (with no ref) below as well, // rust will infer &s and ref tail. // See https://doc.rust-lang.org/edition-guide/rust-2018/ownership-and-lifetimes/default-match-bindings.html match *self { // Can't take ownership of the tail, because `self` is borrowed; // instead take a reference to the tail Cons(_, ref tail) => 1 + tail.len(), // Base Case: An empty list has zero length Nil => 0 } } // Return representation of the list as a (heap allocated) string fn stringify(&self) -> String { match *self { Cons(head, __ tail) => { // `format!` is similar to `print!`, but returns a heap // allocated string instead of printing to the console format!("{}, {}", head, tail.__()) }, Nil => { format!("Nil") }, } } } fn main() { // Create an empty linked list let mut list = List::new(); // Prepend some elements list = list.prepend(1); list = list.prepend(2); list = list.prepend(3); // Show the final state of the list println!("linked list has length: {}", list.len()); println!("{}", list.stringify()); } ``` > You can find the solutions [here](https://github.com/sunface/rust-by-practice)(under the solutions path), but only use it when you need it