]> git.proxmox.com Git - rustc.git/blob - src/doc/book/enums.md
Imported Upstream version 1.6.0+dfsg1
[rustc.git] / src / doc / book / enums.md
1 % Enums
2
3 An `enum` in Rust is a type that represents data that could be one of
4 several possible variants:
5
6 ```rust
7 enum Message {
8 Quit,
9 ChangeColor(i32, i32, i32),
10 Move { x: i32, y: i32 },
11 Write(String),
12 }
13 ```
14
15 Each variant can optionally have data associated with it. The syntax for
16 defining variants resembles the syntaxes used to define structs: you can
17 have variants with no data (like unit-like structs), variants with named
18 data, and variants with unnamed data (like tuple structs). Unlike
19 separate struct definitions, however, an `enum` is a single type. A
20 value of the enum can match any of the variants. For this reason, an
21 enum is sometimes called a ‘sum type’: the set of possible values of the
22 enum is the sum of the sets of possible values for each variant.
23
24 We use the `::` syntax to use the name of each variant: they’re scoped by the name
25 of the `enum` itself. This allows both of these to work:
26
27 ```rust
28 # enum Message {
29 # Move { x: i32, y: i32 },
30 # }
31 let x: Message = Message::Move { x: 3, y: 4 };
32
33 enum BoardGameTurn {
34 Move { squares: i32 },
35 Pass,
36 }
37
38 let y: BoardGameTurn = BoardGameTurn::Move { squares: 1 };
39 ```
40
41 Both variants are named `Move`, but since they’re scoped to the name of
42 the enum, they can both be used without conflict.
43
44 A value of an enum type contains information about which variant it is,
45 in addition to any data associated with that variant. This is sometimes
46 referred to as a ‘tagged union’, since the data includes a ‘tag’
47 indicating what type it is. The compiler uses this information to
48 enforce that you’re accessing the data in the enum safely. For instance,
49 you can’t simply try to destructure a value as if it were one of the
50 possible variants:
51
52 ```rust,ignore
53 fn process_color_change(msg: Message) {
54 let Message::ChangeColor(r, g, b) = msg; // compile-time error
55 }
56 ```
57
58 Not supporting these operations may seem rather limiting, but it’s a limitation
59 which we can overcome. There are two ways: by implementing equality ourselves,
60 or by pattern matching variants with [`match`][match] expressions, which you’ll
61 learn in the next section. We don’t know enough about Rust to implement
62 equality yet, but we’ll find out in the [`traits`][traits] section.
63
64 [match]: match.html
65 [if-let]: if-let.html
66 [traits]: traits.html
67
68 # Constructors as functions
69
70 An enum’s constructors can also be used like functions. For example:
71
72 ```rust
73 # enum Message {
74 # Write(String),
75 # }
76 let m = Message::Write("Hello, world".to_string());
77 ```
78
79 Is the same as
80
81 ```rust
82 # enum Message {
83 # Write(String),
84 # }
85 fn foo(x: String) -> Message {
86 Message::Write(x)
87 }
88
89 let x = foo("Hello, world".to_string());
90 ```
91
92 This is not immediately useful to us, but when we get to
93 [`closures`][closures], we’ll talk about passing functions as arguments to
94 other functions. For example, with [`iterators`][iterators], we can do this
95 to convert a vector of `String`s into a vector of `Message::Write`s:
96
97 ```rust
98 # enum Message {
99 # Write(String),
100 # }
101
102 let v = vec!["Hello".to_string(), "World".to_string()];
103
104 let v1: Vec<Message> = v.into_iter().map(Message::Write).collect();
105 ```
106
107 [closures]: closures.html
108 [iterators]: iterators.html