1
1
% Enums
2
2
3
- Finally, Rust has a "sum type", an * enum* . Enums are an incredibly useful
4
- feature of Rust, and are used throughout the standard library. An ` enum ` is
5
- a type which relates a set of alternates to a specific name. For example, below
6
- we define ` Character ` to be either a ` Digit ` or something else. These
7
- can be used via their fully scoped names: ` Character::Other ` (more about ` :: `
8
- below).
3
+ Rust has a ‘sum type’, an ` enum ` . Enums are an incredibly useful feature of
4
+ Rust, and are used throughout the standard library. An ` enum ` is a type which
5
+ relates a set of alternates to a specific name. For example, below we define
6
+ ` Character ` to be either a ` Digit ` or something else.
9
7
10
8
``` rust
11
9
enum Character {
@@ -14,14 +12,14 @@ enum Character {
14
12
}
15
13
```
16
14
17
- Most normal types are allowed as the variant components of an ` enum ` . Here are
18
- some examples:
15
+ Most types are allowed as the variant components of an ` enum ` . Here are some
16
+ examples:
19
17
20
18
``` rust
21
19
struct Empty ;
22
20
struct Color (i32 , i32 , i32 );
23
21
struct Length (i32 );
24
- struct Status { Health : i32 , Mana : i32 , Attack : i32 , Defense : i32 }
22
+ struct Stats { Health : i32 , Mana : i32 , Attack : i32 , Defense : i32 }
25
23
struct HeightDatabase (Vec <i32 >);
26
24
```
27
25
@@ -30,12 +28,12 @@ In `Character`, for instance, `Digit` gives a meaningful name for an `i32`
30
28
value, where ` Other ` is only a name. However, the fact that they represent
31
29
distinct categories of ` Character ` is a very useful property.
32
30
33
- As with structures, the variants of an enum by default are not comparable with
34
- equality operators (` == ` , ` != ` ), have no ordering (` < ` , ` >= ` , etc.), and do not
35
- support other binary operations such as ` * ` and ` + ` . As such, the following code
36
- is invalid for the example ` Character ` type:
31
+ The variants of an ` enum ` by default are not comparable with equality operators
32
+ (` == ` , ` != ` ), have no ordering (` < ` , ` >= ` , etc.), and do not support other
33
+ binary operations such as ` * ` and ` + ` . As such, the following code is invalid
34
+ for the example ` Character ` type:
37
35
38
- ``` { rust,ignore}
36
+ ``` rust,ignore
39
37
// These assignments both succeed
40
38
let ten = Character::Digit(10);
41
39
let four = Character::Digit(4);
@@ -50,98 +48,21 @@ let four_is_smaller = four <= ten;
50
48
let four_equals_ten = four == ten;
51
49
```
52
50
53
- This may seem rather limiting, but it's a limitation which we can overcome.
54
- There are two ways: by implementing equality ourselves, or by pattern matching
55
- variants with [ ` match ` ] [ match ] expressions, which you'll learn in the next
56
- chapter. We don't know enough about Rust to implement equality yet, but we can
57
- use the ` Ordering ` enum from the standard library, which does:
51
+ We use the ` :: ` syntax to use the name of each variant: They’re scoped by the name
52
+ of the ` enum ` itself. This allows both of these to work:
58
53
59
- ```
60
- enum Ordering {
61
- Less,
62
- Equal,
63
- Greater,
64
- }
65
- ```
66
-
67
- Because ` Ordering ` has already been defined for us, we will import it with the
68
- ` use ` keyword. Here's an example of how it is used:
69
-
70
- ``` {rust}
71
- use std::cmp::Ordering;
72
-
73
- fn cmp(a: i32, b: i32) -> Ordering {
74
- if a < b { Ordering::Less }
75
- else if a > b { Ordering::Greater }
76
- else { Ordering::Equal }
77
- }
78
-
79
- fn main() {
80
- let x = 5;
81
- let y = 10;
82
-
83
- let ordering = cmp(x, y); // ordering: Ordering
84
-
85
- if ordering == Ordering::Less {
86
- println!("less");
87
- } else if ordering == Ordering::Greater {
88
- println!("greater");
89
- } else if ordering == Ordering::Equal {
90
- println!("equal");
91
- }
92
- }
93
- ```
94
-
95
- The ` :: ` symbol is used to indicate a namespace. In this case, ` Ordering ` lives
96
- in the ` cmp ` submodule of the ` std ` module. We'll talk more about modules later
97
- in the guide. For now, all you need to know is that you can ` use ` things from
98
- the standard library if you need them.
99
-
100
- Okay, let's talk about the actual code in the example. ` cmp ` is a function that
101
- compares two things, and returns an ` Ordering ` . We return either
102
- ` Ordering::Less ` , ` Ordering::Greater ` , or ` Ordering::Equal ` , depending on
103
- whether the first value is less than, greater than, or equal to the second. Note
104
- that each variant of the ` enum ` is namespaced under the ` enum ` itself: it's
105
- ` Ordering::Greater ` , not ` Greater ` .
106
-
107
- The ` ordering ` variable has the type ` Ordering ` , and so contains one of the
108
- three values. We then do a bunch of ` if ` /` else ` comparisons to check which
109
- one it is.
110
-
111
- This ` Ordering::Greater ` notation is too long. Let's use another form of ` use `
112
- to import the ` enum ` variants instead. This will avoid full scoping:
113
-
114
- ``` {rust}
115
- use std::cmp::Ordering::{self, Equal, Less, Greater};
116
-
117
- fn cmp(a: i32, b: i32) -> Ordering {
118
- if a < b { Less }
119
- else if a > b { Greater }
120
- else { Equal }
121
- }
122
-
123
- fn main() {
124
- let x = 5;
125
- let y = 10;
126
-
127
- let ordering = cmp(x, y); // ordering: Ordering
128
-
129
- if ordering == Less { println!("less"); }
130
- else if ordering == Greater { println!("greater"); }
131
- else if ordering == Equal { println!("equal"); }
132
- }
54
+ ``` rust,ignore
55
+ Character::Digit(10);
56
+ Hand::Digit;
133
57
```
134
58
135
- Importing variants is convenient and compact, but can also cause name conflicts,
136
- so do this with caution. For this reason, it's normally considered better style
137
- to ` use ` an enum rather than its variants directly.
59
+ Both variants are named ` Digit ` , but since they’re scoped to the ` enum ` name,
138
60
139
- As you can see, ` enum ` s are quite a powerful tool for data representation, and
140
- are even more useful when they're [ generic] [ generics ] across types. Before we
141
- get to generics, though, let's talk about how to use enums with pattern
142
- matching, a tool that will let us deconstruct sum types (the type theory term
143
- for enums) like ` Ordering ` in a very elegant way that avoids all these messy
144
- and brittle ` if ` /` else ` s.
61
+ Not supporting these operations may seem rather limiting, but it’s a limitation
62
+ which we can overcome. There are two ways: by implementing equality ourselves,
63
+ or by pattern matching variants with [ ` match ` ] [ match ] expressions, which you’ll
64
+ learn in the next section. We don’t know enough about Rust to implement
65
+ equality yet, but we’ll find out in the [ ` traits ` ] [ traits ] section.
145
66
146
- [ match ] : ./ match.html
147
- [ generics ] : ./generics .html
67
+ [ match ] : match.html
68
+ [ traits ] : traits .html
0 commit comments