rust-by-practice/en/src/compound-types/enum.md

211 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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<T>` 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<i32>) -> Option<i32> {
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<List>),
// 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