rust-by-practice/solutions/compound-types/enum.md

192 lines
3.9 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.

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<i32>) -> Option<i32> {
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<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) -> 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());
}
```