diff --git a/solutions/compound-types/enum.md b/solutions/compound-types/enum.md index e69de29..4713d9c 100644 --- a/solutions/compound-types/enum.md +++ b/solutions/compound-types/enum.md @@ -0,0 +1,186 @@ +1. +```rust +enum Number { + Zero, + One, + Two, +} + +enum Number1 { + Zero = 0, + One, + Two, +} + +// C-like enum +enum Number2 { + Zero = 0, + One = 1, + Two = 2, +} + + +fn main() { + // a enum variant can be converted to a integer by `as` + assert_eq!(Number::One as u8, Number1::One as u8); + assert_eq!(Number1::One as u8, Number2::One as u8); +} +``` + +2. +```rust +enum Message { + Quit, + Move { x: i32, y: i32 }, + Write(String), + ChangeColor(i32, i32, i32), +} + +fn main() { + let msg1 = Message::Move{x: 1, y: 2}; // instantiating with x = 1, y = 2 + let msg2 = Message::Write(String::from("hello, world")); // instantiating with "hello, world!" +} +``` + +3. +```rust +enum Message { + Quit, + Move { x: i32, y: i32 }, + Write(String), + ChangeColor(i32, i32, i32), +} + +fn main() { + let msg = Message::Move{x: 1, y: 1}; + + if let Message::Move{x: a, y: b} = msg { + assert_eq!(a, b); + } else { + panic!("NEVER LET THIS RUN๏ผ"); + } +} +``` + +4. +```rust +#[derive(Debug)] +enum Message { + Quit, + Move { x: i32, y: i32 }, + Write(String), + ChangeColor(i32, i32, i32), +} + +fn main() { + let msgs: [Message; 3] = [ + 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. +```rust +fn main() { + let five = Some(5); + let six = plus_one(five); + let none = plus_one(None); + + if let Some(n) = six { + println!("{}", n); + return + } + + panic!("NEVER LET THIS RUN๏ผ"); +} + +fn plus_one(x: Option) -> Option { + match x { + None => None, + Some(i) => Some(i + 1), + } +} +``` + +6. +```rust +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) -> List { + // `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, ref tail) => { + // `format!` is similar to `print!`, but returns a heap + // allocated string instead of printing to the console + format!("{}, {}", head, tail.stringify()) + }, + 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()); +} +``` \ No newline at end of file diff --git a/src/compound-types/enum.md b/src/compound-types/enum.md index 3f09e2f..092492f 100644 --- a/src/compound-types/enum.md +++ b/src/compound-types/enum.md @@ -1,5 +1,5 @@ # Enum -๐ŸŒŸ๐ŸŒŸ Enums can be created with explicit discriminator. +1. ๐ŸŒŸ๐ŸŒŸ Enums can be created with explicit discriminator. ```rust,editable @@ -31,7 +31,7 @@ fn main() { } ``` -๐ŸŒŸ each enum variant can hold its own data. +2. ๐ŸŒŸ each enum variant can hold its own data. ```rust,editable // fill in the blank @@ -48,10 +48,10 @@ fn main() { } ``` -๐ŸŒŸ๐ŸŒŸ we can get the data which a enum variant is holding by pattern match +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 }, @@ -60,7 +60,7 @@ enum Message { } fn main() { - let msg = Message::Move{x: 1, y: 1}; + let msg = Message::Move{x: 1, y: 2}; if let Message::Move{__} = msg { assert_eq!(a, b); @@ -70,7 +70,7 @@ fn main() { } ``` -๐ŸŒŸ๐ŸŒŸ +4. ๐ŸŒŸ๐ŸŒŸ ```rust,editable @@ -99,7 +99,7 @@ fn show_message(msg: Message) { } ``` -๐ŸŒŸ๐ŸŒŸ As there is no `null` in Rust, we have to use enum `Option` to deal the cases when value is absent. +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. @@ -125,7 +125,7 @@ fn plus_one(x: Option) -> Option { ``` -๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ implement a `linked-list` via enums. +6. ๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ implement a `linked-list` via enums. ```rust,editable diff --git a/zh-CN/src/compound-types/enum.md b/zh-CN/src/compound-types/enum.md index 21ba5f5..7733b3b 100644 --- a/zh-CN/src/compound-types/enum.md +++ b/zh-CN/src/compound-types/enum.md @@ -51,7 +51,7 @@ fn main() { ๐ŸŒŸ๐ŸŒŸ ๆžšไธพๆˆๅ‘˜ไธญ็š„ๅ€ผๅฏไปฅไฝฟ็”จๆจกๅผๅŒน้…ๆฅ่Žทๅ– ```rust,editable -// ไป…ๅกซ็ฉบ๏ผŒไธ่ฆไฟฎๆ”นๅ…ถๅฎƒไปฃ็ ๏ผ +// ไป…ๅกซ็ฉบๅนถไฟฎๅค้”™่ฏฏ enum Message { Quit, Move { x: i32, y: i32 }, @@ -60,7 +60,7 @@ enum Message { } fn main() { - let msg = Message::Move{x: 1, y: 1}; + let msg = Message::Move{x: 1, y: 2}; if let Message::Move{__} = msg { assert_eq!(a, b);