官术网_书友最值得收藏!

  • Mastering Rust
  • Rahul Sharma Vesa Kaihlavirta
  • 527字
  • 2021-07-02 13:35:16

Enums

When you need to model something that can be of different kinds, enums are the way to go. They are created using the enum keyword, followed by the name of the enum, followed by a pair of braces. Within braces, we can write all the possibilities of the type, which are called variants. These variants can be defined with or without data contained in them, and the data contained can be any primitive type, structs, tuple structs, or even an enum. However, in the recursive case, where you have an enum, Foo, and also a variant which holds Foo, the variant needs to be behind a pointer (Box, Rc, and so on) type to avoid having recursively infinite type definitions. Because enums can also be created on the stack, they need to have a predetermined size, and infinite type definitions makes it impossible to determine the size at compile time. Now, let's take a look at how to create one:

// enums.rs

enum Direction {
N,
E,
S,
W
}

enum PlayerAction {
Move {
direction: Direction,
speed: u8
},
Wait,
Attack(Direction)
}

fn main() {
let simulated_player_action = PlayerAction::Move {
direction: Direction::N,
speed: 2,
};
match simulated_player_action {
PlayerAction::Wait => println!("Player wants to wait"),
PlayerAction::Move { direction, speed } => {
println!("Player wants to move in direction {:?} with speed {}",
direction, speed)
}
PlayerAction::Attack(direction) => {
println!("Player wants to attack direction {:?}", direction)
}
};
}

The preceding code defines two enum types: Direction and PlayerAction. We then create an instance of them by choosing any variant, such as Direction::N or PlayerAction::Wait using the double colon :: in between. Note that we can't have something like an uninitialized enum, and it needs to be one of the variants. Given an enum value, to see what variant an enum instance has, we use pattern matching by using match expressions. When we match on enums, we can directly destructure the contents of the variants by putting variables in place of fields such as direction in PlayerAction::Attack(direction), which in turn means that we can use them inside our match arms.

As you can see in our preceding Direction enum, we have a #[derive(Debug)] annotation. This is an attribute and it allows Direction instances to be printed using the {:?} format string in println!(). This is done by generating methods from a trait called Debug. The compiler tells us whether the Debug trait is missing and gives suggestions about how to fix it, and so we need the attribute there:

From a functional programmer's perspective, structs and enums are also known as Algebraic Data Types (ADTs) because the possible range of values they can represent can be expressed using the rules of algebra. For instance, an enum is called a sum type because the range of values that it can hold is basically the sum of the range of values of its variants, while a struct is called a product type because its range of possible values is the cartesian product of their individual fields' range of values. We'll sometime refer to them as ADTs when talking about them in general.

主站蜘蛛池模板: 华蓥市| 浦东新区| 滦平县| 永兴县| 苍山县| 株洲市| 郓城县| 安阳市| 永修县| 康保县| 若羌县| 龙门县| 庆云县| 逊克县| 贵德县| 闵行区| 元谋县| 齐河县| 平乡县| 五指山市| 澄江县| 漳州市| 西吉县| 图们市| 湟源县| 宜兴市| 福清市| 康马县| 龙胜| 夏津县| 凤凰县| 揭阳市| 灵山县| 清远市| 抚州市| 灵台县| 榆中县| 石泉县| 雅安市| 当涂县| 肇州县|