11% Enums
22
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.
97
108``` rust
119enum Character {
@@ -14,14 +12,14 @@ enum Character {
1412}
1513```
1614
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:
1917
2018``` rust
2119struct Empty ;
2220struct Color (i32 , i32 , i32 );
2321struct Length (i32 );
24- struct Status { Health : i32 , Mana : i32 , Attack : i32 , Defense : i32 }
22+ struct Stats { Health : i32 , Mana : i32 , Attack : i32 , Defense : i32 }
2523struct HeightDatabase (Vec <i32 >);
2624```
2725
@@ -30,12 +28,12 @@ In `Character`, for instance, `Digit` gives a meaningful name for an `i32`
3028value, where ` Other ` is only a name. However, the fact that they represent
3129distinct categories of ` Character ` is a very useful property.
3230
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:
3735
38- ``` { rust,ignore}
36+ ``` rust,ignore
3937// These assignments both succeed
4038let ten = Character::Digit(10);
4139let four = Character::Digit(4);
@@ -50,98 +48,21 @@ let four_is_smaller = four <= ten;
5048let four_equals_ten = four == ten;
5149```
5250
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:
5853
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;
13357```
13458
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,
13860
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.
14566
146- [ match ] : ./ match.html
147- [ generics ] : ./generics .html
67+ [ match ] : match.html
68+ [ traits ] : traits .html
0 commit comments