]>
Commit | Line | Data |
---|---|---|
13cf67c4 XL |
1 | # Programming a Guessing Game |
2 | ||
3 | Let’s jump into Rust by working through a hands-on project together! This | |
4 | chapter introduces you to a few common Rust concepts by showing you how to use | |
5 | them in a real program. You’ll learn about `let`, `match`, methods, associated | |
3c0e092e XL |
6 | functions, using external crates, and more! In the following chapters, we’ll |
7 | explore these ideas in more detail. In this chapter, you’ll practice the | |
8 | fundamentals. | |
13cf67c4 XL |
9 | |
10 | We’ll implement a classic beginner programming problem: a guessing game. Here’s | |
11 | how it works: the program will generate a random integer between 1 and 100. It | |
12 | will then prompt the player to enter a guess. After a guess is entered, the | |
13 | program will indicate whether the guess is too low or too high. If the guess is | |
14 | correct, the game will print a congratulatory message and exit. | |
15 | ||
16 | ## Setting Up a New Project | |
17 | ||
18 | To set up a new project, go to the *projects* directory that you created in | |
19 | Chapter 1 and make a new project using Cargo, like so: | |
20 | ||
f035d41b | 21 | ```console |
13cf67c4 XL |
22 | $ cargo new guessing_game |
23 | $ cd guessing_game | |
24 | ``` | |
25 | ||
26 | The first command, `cargo new`, takes the name of the project (`guessing_game`) | |
27 | as the first argument. The second command changes to the new project’s | |
28 | directory. | |
29 | ||
30 | Look at the generated *Cargo.toml* file: | |
31 | ||
32 | <span class="filename">Filename: Cargo.toml</span> | |
33 | ||
34 | ```toml | |
74b04a01 | 35 | {{#include ../listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.toml}} |
13cf67c4 XL |
36 | ``` |
37 | ||
13cf67c4 XL |
38 | As you saw in Chapter 1, `cargo new` generates a “Hello, world!” program for |
39 | you. Check out the *src/main.rs* file: | |
40 | ||
41 | <span class="filename">Filename: src/main.rs</span> | |
42 | ||
43 | ```rust | |
74b04a01 | 44 | {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/src/main.rs}} |
13cf67c4 XL |
45 | ``` |
46 | ||
47 | Now let’s compile this “Hello, world!” program and run it in the same step | |
48 | using the `cargo run` command: | |
49 | ||
f035d41b | 50 | ```console |
74b04a01 | 51 | {{#include ../listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/output.txt}} |
13cf67c4 XL |
52 | ``` |
53 | ||
54 | The `run` command comes in handy when you need to rapidly iterate on a project, | |
55 | as we’ll do in this game, quickly testing each iteration before moving on to | |
56 | the next one. | |
57 | ||
58 | Reopen the *src/main.rs* file. You’ll be writing all the code in this file. | |
59 | ||
60 | ## Processing a Guess | |
61 | ||
62 | The first part of the guessing game program will ask for user input, process | |
63 | that input, and check that the input is in the expected form. To start, we’ll | |
64 | allow the player to input a guess. Enter the code in Listing 2-1 into | |
65 | *src/main.rs*. | |
66 | ||
67 | <span class="filename">Filename: src/main.rs</span> | |
68 | ||
69 | ```rust,ignore | |
74b04a01 | 70 | {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:all}} |
13cf67c4 XL |
71 | ``` |
72 | ||
73 | <span class="caption">Listing 2-1: Code that gets a guess from the user and | |
74 | prints it</span> | |
75 | ||
76 | This code contains a lot of information, so let’s go over it line by line. To | |
77 | obtain user input and then print the result as output, we need to bring the | |
3c0e092e XL |
78 | `io` input/output library into scope. The `io` library comes from the |
79 | standard library, known as `std`: | |
13cf67c4 XL |
80 | |
81 | ```rust,ignore | |
74b04a01 | 82 | {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:io}} |
13cf67c4 XL |
83 | ``` |
84 | ||
3c0e092e XL |
85 | By default, Rust has a few items defined in the standard library that it brings |
86 | into the scope of every program. This set is called the *prelude*, and you can | |
87 | see everything in it [in the standard library documentation][prelude]. | |
13cf67c4 | 88 | |
3c0e092e XL |
89 | If a type you want to use isn’t in the prelude, you have to bring that type |
90 | into scope explicitly with a `use` statement. Using the `std::io` library | |
91 | provides you with a number of useful features, including the ability to accept | |
92 | user input. | |
13cf67c4 XL |
93 | |
94 | As you saw in Chapter 1, the `main` function is the entry point into the | |
95 | program: | |
96 | ||
97 | ```rust,ignore | |
74b04a01 | 98 | {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:main}} |
13cf67c4 XL |
99 | ``` |
100 | ||
101 | The `fn` syntax declares a new function, the parentheses, `()`, indicate there | |
102 | are no parameters, and the curly bracket, `{`, starts the body of the function. | |
103 | ||
104 | As you also learned in Chapter 1, `println!` is a macro that prints a string to | |
105 | the screen: | |
106 | ||
107 | ```rust,ignore | |
74b04a01 | 108 | {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:print}} |
13cf67c4 XL |
109 | ``` |
110 | ||
111 | This code is printing a prompt stating what the game is and requesting input | |
112 | from the user. | |
113 | ||
114 | ### Storing Values with Variables | |
115 | ||
3c0e092e | 116 | Next, we’ll create a *variable* to store the user input, like this: |
13cf67c4 XL |
117 | |
118 | ```rust,ignore | |
74b04a01 | 119 | {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:string}} |
13cf67c4 XL |
120 | ``` |
121 | ||
122 | Now the program is getting interesting! There’s a lot going on in this little | |
3c0e092e | 123 | line. We use the `let` statement to create the variable. Here’s another example: |
13cf67c4 XL |
124 | |
125 | ```rust,ignore | |
136023e0 | 126 | let apples = 5; |
13cf67c4 XL |
127 | ``` |
128 | ||
136023e0 XL |
129 | This line creates a new variable named `apples` and binds it to the value 5. In |
130 | Rust, variables are immutable by default. We’ll be discussing this concept in | |
131 | detail in the [“Variables and Mutability”][variables-and-mutability]<!-- ignore | |
3c0e092e XL |
132 | --> section in Chapter 3. To make a variable mutable, we add `mut` before the |
133 | variable name: | |
13cf67c4 XL |
134 | |
135 | ```rust,ignore | |
136023e0 XL |
136 | let apples = 5; // immutable |
137 | let mut bananas = 5; // mutable | |
13cf67c4 XL |
138 | ``` |
139 | ||
140 | > Note: The `//` syntax starts a comment that continues until the end of the | |
3c0e092e XL |
141 | > line. Rust ignores everything in comments. We’ll discuss comments in more |
142 | > detail in [Chapter 3][comments]<!-- ignore -->. | |
143 | ||
144 | Returning to the guessing game program, you now know that `let mut guess` will | |
145 | introduce a mutable variable named `guess`. The equal sign (`=`) tells Rust we | |
146 | want to bind something to the variable now. On the right of the equals sign is | |
147 | the value that `guess` is bound to, which is the result of calling | |
148 | `String::new`, a function that returns a new instance of a `String`. | |
69743fb6 XL |
149 | [`String`][string]<!-- ignore --> is a string type provided by the standard |
150 | library that is a growable, UTF-8 encoded bit of text. | |
13cf67c4 | 151 | |
3c0e092e XL |
152 | The `::` syntax in the `::new` line indicates that `new` is an associated |
153 | function of the `String` type. An *associated function* is a function that’s | |
154 | implemented on a type, in this case `String`. This `new` function creates a | |
155 | new, empty string. You’ll find a `new` function on many types, because it’s a | |
156 | common name for a function that makes a new value of some kind. | |
13cf67c4 | 157 | |
3c0e092e | 158 | In full, the `let mut guess = String::new();` line has created a mutable |
13cf67c4 XL |
159 | variable that is currently bound to a new, empty instance of a `String`. Whew! |
160 | ||
3c0e092e XL |
161 | ### Receiving User Input |
162 | ||
13cf67c4 | 163 | Recall that we included the input/output functionality from the standard |
532ac7d7 | 164 | library with `use std::io;` on the first line of the program. Now we’ll call |
3c0e092e XL |
165 | the `stdin` function from the `io` module, which will allow us to handle user |
166 | input: | |
13cf67c4 XL |
167 | |
168 | ```rust,ignore | |
74b04a01 | 169 | {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:read}} |
13cf67c4 XL |
170 | ``` |
171 | ||
3c0e092e XL |
172 | If we hadn’t imported the `io` library with `use std::io` at the beginning of |
173 | the program, we could still use the function by writing this function call as | |
174 | `std::io::stdin`. The `stdin` function returns an instance of | |
175 | [`std::io::Stdin`][iostdin]<!-- ignore -->, which is a type that represents a | |
176 | handle to the standard input for your terminal. | |
13cf67c4 | 177 | |
3c0e092e XL |
178 | Next, the line `.read_line(&mut guess)` calls the [`read_line`][read_line]<!-- |
179 | ignore --> method on the standard input handle to get input from the user. | |
180 | We’re also passing `&mut guess` as the argument to `read_line` to tell it what | |
181 | string to store the user input in. The full job of `read_line` is to take | |
182 | whatever the user types into standard input and append that into a string | |
183 | (without overwriting its contents), so we therefore pass that string as an | |
184 | argument. The string argument needs to be mutable so the method can change the | |
185 | string’s content. | |
13cf67c4 XL |
186 | |
187 | The `&` indicates that this argument is a *reference*, which gives you a way to | |
188 | let multiple parts of your code access one piece of data without needing to | |
189 | copy that data into memory multiple times. References are a complex feature, | |
190 | and one of Rust’s major advantages is how safe and easy it is to use | |
191 | references. You don’t need to know a lot of those details to finish this | |
192 | program. For now, all you need to know is that like variables, references are | |
193 | immutable by default. Hence, you need to write `&mut guess` rather than | |
194 | `&guess` to make it mutable. (Chapter 4 will explain references more | |
195 | thoroughly.) | |
196 | ||
197 | ### Handling Potential Failure with the `Result` Type | |
198 | ||
74b04a01 XL |
199 | We’re still working on this line of code. Although we’re now discussing a third |
200 | line of text, it’s still part of a single logical line of code. The next part | |
201 | is this method: | |
13cf67c4 XL |
202 | |
203 | ```rust,ignore | |
74b04a01 | 204 | {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:expect}} |
13cf67c4 XL |
205 | ``` |
206 | ||
3c0e092e | 207 | We could have written this code as: |
13cf67c4 XL |
208 | |
209 | ```rust,ignore | |
210 | io::stdin().read_line(&mut guess).expect("Failed to read line"); | |
211 | ``` | |
212 | ||
3c0e092e XL |
213 | However, one long line is difficult to read, so it’s best to divide it. It’s |
214 | often wise to introduce a newline and other whitespace to help break up long | |
215 | lines when you call a method with the `.method_name()` syntax. Now let’s | |
216 | discuss what this line does. | |
13cf67c4 | 217 | |
3c0e092e XL |
218 | As mentioned earlier, `read_line` puts whatever the user enters into the string |
219 | we pass to it, but it also returns a value—in this case, an | |
13cf67c4 XL |
220 | [`io::Result`][ioresult]<!-- ignore -->. Rust has a number of types named |
221 | `Result` in its standard library: a generic [`Result`][result]<!-- ignore --> | |
3c0e092e XL |
222 | as well as specific versions for submodules, such as `io::Result`. The `Result` |
223 | types are [*enumerations*][enums]<!-- ignore -->, often referred to as *enums*, | |
a2a8927a XL |
224 | which can have a fixed set of possibilities known as *variants*. Enums are |
225 | often used with `match`, a conditional that makes it convenient to execute | |
226 | different code based on which variant an enum value is when the conditional is | |
227 | evaluated. | |
13cf67c4 | 228 | |
3c0e092e XL |
229 | Chapter 6 will cover enums in more detail. The purpose of these `Result` types |
230 | is to encode error-handling information. | |
13cf67c4 | 231 | |
3c0e092e XL |
232 | `Result`’s variants are `Ok` or `Err`. The `Ok` variant indicates the operation |
233 | was successful, and inside `Ok` is the successfully generated value. The `Err` | |
234 | variant means the operation failed, and `Err` contains information about how or | |
235 | why the operation failed. | |
13cf67c4 | 236 | |
69743fb6 XL |
237 | Values of the `Result` type, like values of any type, have methods defined on |
238 | them. An instance of `io::Result` has an [`expect` method][expect]<!-- ignore | |
239 | --> that you can call. If this instance of `io::Result` is an `Err` value, | |
240 | `expect` will cause the program to crash and display the message that you | |
241 | passed as an argument to `expect`. If the `read_line` method returns an `Err`, | |
242 | it would likely be the result of an error coming from the underlying operating | |
243 | system. If this instance of `io::Result` is an `Ok` value, `expect` will take | |
244 | the return value that `Ok` is holding and return just that value to you so you | |
3c0e092e | 245 | can use it. In this case, that value is the number of bytes in the user’s input. |
13cf67c4 XL |
246 | |
247 | If you don’t call `expect`, the program will compile, but you’ll get a warning: | |
248 | ||
f035d41b | 249 | ```console |
74b04a01 | 250 | {{#include ../listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt}} |
13cf67c4 XL |
251 | ``` |
252 | ||
253 | Rust warns that you haven’t used the `Result` value returned from `read_line`, | |
254 | indicating that the program hasn’t handled a possible error. | |
255 | ||
256 | The right way to suppress the warning is to actually write error handling, but | |
3c0e092e XL |
257 | in our case we just want to crash this program when a problem occurs, so we can |
258 | use `expect`. You’ll learn about recovering from errors in [Chapter | |
259 | 9][recover]<!-- ignore -->. | |
13cf67c4 XL |
260 | |
261 | ### Printing Values with `println!` Placeholders | |
262 | ||
74b04a01 | 263 | Aside from the closing curly bracket, there’s only one more line to discuss in |
3c0e092e | 264 | the code so far: |
13cf67c4 XL |
265 | |
266 | ```rust,ignore | |
74b04a01 | 267 | {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:print_guess}} |
13cf67c4 XL |
268 | ``` |
269 | ||
3c0e092e XL |
270 | This line prints the string that now contains the user’s input. The `{}` set of |
271 | curly brackets is a placeholder: think of `{}` as little crab pincers that hold | |
272 | a value in place. You can print more than one value using curly brackets: the | |
273 | first set of curly brackets holds the first value listed after the format | |
13cf67c4 XL |
274 | string, the second set holds the second value, and so on. Printing multiple |
275 | values in one call to `println!` would look like this: | |
276 | ||
277 | ```rust | |
278 | let x = 5; | |
279 | let y = 10; | |
280 | ||
281 | println!("x = {} and y = {}", x, y); | |
282 | ``` | |
283 | ||
284 | This code would print `x = 5 and y = 10`. | |
285 | ||
286 | ### Testing the First Part | |
287 | ||
288 | Let’s test the first part of the guessing game. Run it using `cargo run`: | |
289 | ||
74b04a01 XL |
290 | <!-- manual-regeneration |
291 | cd listings/ch02-guessing-game-tutorial/listing-02-01/ | |
292 | cargo clean | |
293 | cargo run | |
294 | input 6 --> | |
295 | ||
f035d41b | 296 | ```console |
13cf67c4 XL |
297 | $ cargo run |
298 | Compiling guessing_game v0.1.0 (file:///projects/guessing_game) | |
74b04a01 | 299 | Finished dev [unoptimized + debuginfo] target(s) in 6.44s |
13cf67c4 XL |
300 | Running `target/debug/guessing_game` |
301 | Guess the number! | |
302 | Please input your guess. | |
303 | 6 | |
304 | You guessed: 6 | |
305 | ``` | |
306 | ||
307 | At this point, the first part of the game is done: we’re getting input from the | |
308 | keyboard and then printing it. | |
309 | ||
310 | ## Generating a Secret Number | |
311 | ||
312 | Next, we need to generate a secret number that the user will try to guess. The | |
313 | secret number should be different every time so the game is fun to play more | |
3c0e092e | 314 | than once. We’ll use a random number between 1 and 100 so the game isn’t too |
13cf67c4 | 315 | difficult. Rust doesn’t yet include random number functionality in its standard |
3c0e092e XL |
316 | library. However, the Rust team does provide a [`rand` crate][randcrate] with |
317 | said functionality. | |
13cf67c4 XL |
318 | |
319 | ### Using a Crate to Get More Functionality | |
320 | ||
136023e0 XL |
321 | Remember that a crate is a collection of Rust source code files. The project |
322 | we’ve been building is a *binary crate*, which is an executable. The `rand` | |
323 | crate is a *library crate*, which contains code intended to be used in other | |
3c0e092e | 324 | programs, and can’t be executed on its own. |
13cf67c4 | 325 | |
136023e0 XL |
326 | Cargo’s coordination of external crates is where Cargo really shines. Before we |
327 | can write code that uses `rand`, we need to modify the *Cargo.toml* file to | |
328 | include the `rand` crate as a dependency. Open that file now and add the | |
329 | following line to the bottom beneath the `[dependencies]` section header that | |
3c0e092e XL |
330 | Cargo created for you. Be sure to specify `rand` exactly as we have here, with |
331 | this version number, or the code examples in this tutorial may not work. | |
13cf67c4 | 332 | |
e74abb32 XL |
333 | <!-- When updating the version of `rand` used, also update the version of |
334 | `rand` used in these files so they all match: | |
335 | * ch07-04-bringing-paths-into-scope-with-the-use-keyword.md | |
336 | * ch14-03-cargo-workspaces.md | |
337 | --> | |
338 | ||
13cf67c4 XL |
339 | <span class="filename">Filename: Cargo.toml</span> |
340 | ||
341 | ```toml | |
74b04a01 | 342 | {{#include ../listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml:9:}} |
13cf67c4 XL |
343 | ``` |
344 | ||
3c0e092e XL |
345 | In the *Cargo.toml* file, everything that follows a header is part of that |
346 | section that continues until another section starts. In `[dependencies]` you | |
347 | tell Cargo which external crates your project depends on and which versions of | |
348 | those crates you require. In this case, we specify the `rand` crate with the | |
349 | semantic version specifier `0.8.3`. Cargo understands [Semantic | |
13cf67c4 | 350 | Versioning][semver]<!-- ignore --> (sometimes called *SemVer*), which is a |
6a06907d XL |
351 | standard for writing version numbers. The number `0.8.3` is actually shorthand |
352 | for `^0.8.3`, which means any version that is at least `0.8.3` but below | |
353 | `0.9.0`. Cargo considers these versions to have public APIs compatible with | |
3c0e092e | 354 | version `0.8.3`, and this specification ensures you’ll get the latest patch |
6a06907d XL |
355 | release that will still compile with the code in this chapter. Any version |
356 | `0.9.0` or greater is not guaranteed to have the same API as what the following | |
357 | examples use. | |
13cf67c4 | 358 | |
13cf67c4 | 359 | Now, without changing any of the code, let’s build the project, as shown in |
69743fb6 | 360 | Listing 2-2. |
13cf67c4 | 361 | |
74b04a01 XL |
362 | <!-- manual-regeneration |
363 | cd listings/ch02-guessing-game-tutorial/listing-02-02/ | |
364 | cargo clean | |
365 | cargo build --> | |
366 | ||
f035d41b | 367 | ```console |
13cf67c4 | 368 | $ cargo build |
e74abb32 | 369 | Updating crates.io index |
6a06907d XL |
370 | Downloaded rand v0.8.3 |
371 | Downloaded libc v0.2.86 | |
372 | Downloaded getrandom v0.2.2 | |
373 | Downloaded cfg-if v1.0.0 | |
374 | Downloaded ppv-lite86 v0.2.10 | |
375 | Downloaded rand_chacha v0.3.0 | |
376 | Downloaded rand_core v0.6.2 | |
377 | Compiling rand_core v0.6.2 | |
378 | Compiling libc v0.2.86 | |
379 | Compiling getrandom v0.2.2 | |
380 | Compiling cfg-if v1.0.0 | |
381 | Compiling ppv-lite86 v0.2.10 | |
382 | Compiling rand_chacha v0.3.0 | |
383 | Compiling rand v0.8.3 | |
13cf67c4 | 384 | Compiling guessing_game v0.1.0 (file:///projects/guessing_game) |
74b04a01 | 385 | Finished dev [unoptimized + debuginfo] target(s) in 2.53s |
13cf67c4 XL |
386 | ``` |
387 | ||
388 | <span class="caption">Listing 2-2: The output from running `cargo build` after | |
389 | adding the rand crate as a dependency</span> | |
390 | ||
3c0e092e XL |
391 | You may see different version numbers (but they will all be compatible with the |
392 | code, thanks to SemVer!), different lines (depending on the operating system), | |
393 | and the lines may be in a different order. | |
13cf67c4 | 394 | |
3c0e092e XL |
395 | When we include an external dependency, Cargo fetches the latest versions of |
396 | everything that dependency needs from the *registry*, which is a copy of data | |
397 | from [Crates.io][cratesio]. Crates.io is where people in the Rust ecosystem | |
398 | post their open source Rust projects for others to use. | |
13cf67c4 XL |
399 | |
400 | After updating the registry, Cargo checks the `[dependencies]` section and | |
3c0e092e XL |
401 | downloads any crates listed that aren’t already downloaded. In this case, |
402 | although we only listed `rand` as a dependency, Cargo also grabbed other crates | |
403 | that `rand` depends on to work. After downloading the crates, Rust compiles | |
404 | them and then compiles the project with the dependencies available. | |
13cf67c4 XL |
405 | |
406 | If you immediately run `cargo build` again without making any changes, you | |
407 | won’t get any output aside from the `Finished` line. Cargo knows it has already | |
408 | downloaded and compiled the dependencies, and you haven’t changed anything | |
409 | about them in your *Cargo.toml* file. Cargo also knows that you haven’t changed | |
410 | anything about your code, so it doesn’t recompile that either. With nothing to | |
411 | do, it simply exits. | |
412 | ||
413 | If you open up the *src/main.rs* file, make a trivial change, and then save it | |
414 | and build again, you’ll only see two lines of output: | |
415 | ||
74b04a01 XL |
416 | <!-- manual-regeneration |
417 | cd listings/ch02-guessing-game-tutorial/listing-02-02/ | |
418 | touch src/main.rs | |
419 | cargo build --> | |
420 | ||
f035d41b | 421 | ```console |
13cf67c4 XL |
422 | $ cargo build |
423 | Compiling guessing_game v0.1.0 (file:///projects/guessing_game) | |
74b04a01 | 424 | Finished dev [unoptimized + debuginfo] target(s) in 2.53 secs |
13cf67c4 XL |
425 | ``` |
426 | ||
427 | These lines show Cargo only updates the build with your tiny change to the | |
428 | *src/main.rs* file. Your dependencies haven’t changed, so Cargo knows it can | |
3c0e092e | 429 | reuse what it has already downloaded and compiled for those. |
13cf67c4 XL |
430 | |
431 | #### Ensuring Reproducible Builds with the *Cargo.lock* File | |
432 | ||
433 | Cargo has a mechanism that ensures you can rebuild the same artifact every time | |
434 | you or anyone else builds your code: Cargo will use only the versions of the | |
3c0e092e XL |
435 | dependencies you specified until you indicate otherwise. For example, say that |
436 | next week version 0.8.4 of the `rand` crate comes out, and that version | |
437 | contains an important bug fix, but it also contains a regression that will | |
438 | break your code. To handle this, Rust creates the *Cargo.lock* file the first | |
439 | time you run `cargo build`, so we now have this in the *guessing_game* | |
440 | directory. | |
13cf67c4 | 441 | |
13cf67c4 XL |
442 | When you build a project for the first time, Cargo figures out all the |
443 | versions of the dependencies that fit the criteria and then writes them to | |
444 | the *Cargo.lock* file. When you build your project in the future, Cargo will | |
445 | see that the *Cargo.lock* file exists and use the versions specified there | |
446 | rather than doing all the work of figuring out versions again. This lets you | |
447 | have a reproducible build automatically. In other words, your project will | |
6a06907d | 448 | remain at `0.8.3` until you explicitly upgrade, thanks to the *Cargo.lock* |
13cf67c4 XL |
449 | file. |
450 | ||
451 | #### Updating a Crate to Get a New Version | |
452 | ||
3c0e092e | 453 | When you *do* want to update a crate, Cargo provides the command `update`, |
13cf67c4 | 454 | which will ignore the *Cargo.lock* file and figure out all the latest versions |
3c0e092e XL |
455 | that fit your specifications in *Cargo.toml*. Cargo will then write those |
456 | versions to the *Cargo.lock* file. Otherwise, by default, Cargo will only look | |
457 | for versions greater than `0.8.3` and less than `0.9.0`. If the `rand` crate | |
458 | has released the two new versions `0.8.4` and `0.9.0` you would see the | |
459 | following if you ran `cargo update`: | |
13cf67c4 | 460 | |
74b04a01 XL |
461 | <!-- manual-regeneration |
462 | cd listings/ch02-guessing-game-tutorial/listing-02-02/ | |
463 | cargo update | |
6a06907d | 464 | assuming there is a new 0.8.x version of rand; otherwise use another update |
74b04a01 XL |
465 | as a guide to creating the hypothetical output shown here --> |
466 | ||
f035d41b | 467 | ```console |
13cf67c4 | 468 | $ cargo update |
e74abb32 | 469 | Updating crates.io index |
6a06907d | 470 | Updating rand v0.8.3 -> v0.8.4 |
13cf67c4 XL |
471 | ``` |
472 | ||
a2a8927a | 473 | Cargo ignores the `0.9.0` release. At this point, you would also notice a |
3c0e092e XL |
474 | change in your *Cargo.lock* file noting that the version of the `rand` crate |
475 | you are now using is `0.8.4`. To use `rand` version `0.9.0` or any version in | |
476 | the `0.9.x` series, you’d have to update the *Cargo.toml* file to look like | |
477 | this instead: | |
13cf67c4 XL |
478 | |
479 | ```toml | |
480 | [dependencies] | |
6a06907d | 481 | rand = "0.9.0" |
13cf67c4 XL |
482 | ``` |
483 | ||
484 | The next time you run `cargo build`, Cargo will update the registry of crates | |
485 | available and reevaluate your `rand` requirements according to the new version | |
486 | you have specified. | |
487 | ||
488 | There’s a lot more to say about [Cargo][doccargo]<!-- ignore --> and [its | |
489 | ecosystem][doccratesio]<!-- ignore --> which we’ll discuss in Chapter 14, but | |
490 | for now, that’s all you need to know. Cargo makes it very easy to reuse | |
491 | libraries, so Rustaceans are able to write smaller projects that are assembled | |
492 | from a number of packages. | |
493 | ||
13cf67c4 XL |
494 | ### Generating a Random Number |
495 | ||
3c0e092e XL |
496 | Let’s start using `rand` to generate a number to guess. The next step is to |
497 | update *src/main.rs*, as shown in Listing 2-3. | |
13cf67c4 XL |
498 | |
499 | <span class="filename">Filename: src/main.rs</span> | |
500 | ||
501 | ```rust,ignore | |
74b04a01 | 502 | {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-03/src/main.rs:all}} |
13cf67c4 XL |
503 | ``` |
504 | ||
505 | <span class="caption">Listing 2-3: Adding code to generate a random | |
506 | number</span> | |
507 | ||
3c0e092e XL |
508 | First, we add the line `use rand::Rng`. The `Rng` trait defines methods that |
509 | random number generators implement, and this trait must be in scope for us to | |
510 | use those methods. Chapter 10 will cover traits in detail. | |
511 | ||
512 | Next, we’re adding two lines in the middle. In the first line, we call the | |
513 | `rand::thread_rng` function that gives us the particular random number | |
514 | generator that we’re going to use: one that is local to the current thread of | |
515 | execution and seeded by the operating system. Then we call the `gen_range` | |
516 | method on the random number generator. This method is defined by the `Rng` | |
517 | trait that we brought into scope with the `use rand::Rng` statement. The | |
518 | `gen_range` method takes a range expression as an argument and generates a | |
519 | random number in the range. The kind of range expression we’re using here takes | |
520 | the form `start..end` and is inclusive on the lower bound but exclusive on the | |
521 | upper bound, so we need to specify `1..101` to request a number between 1 and | |
522 | 100. Alternatively, we could pass the range `1..=100`, which is equivalent. | |
13cf67c4 XL |
523 | |
524 | > Note: You won’t just know which traits to use and which methods and functions | |
3c0e092e XL |
525 | > to call from a crate, so each crate has documentation with instructions for |
526 | > using it. Another neat feature of Cargo is that running the `cargo doc | |
527 | > --open` command will build documentation provided by all of your dependencies | |
528 | > locally and open it in your browser. If you’re interested in other | |
529 | > functionality in the `rand` crate, for example, run `cargo doc --open` and | |
530 | > click `rand` in the sidebar on the left. | |
531 | ||
532 | The second new line prints the secret number. This is useful while we’re | |
533 | developing the program to be able to test it, but we’ll delete it from the | |
534 | final version. It’s not much of a game if the program prints the answer as soon | |
535 | as it starts! | |
13cf67c4 XL |
536 | |
537 | Try running the program a few times: | |
538 | ||
74b04a01 XL |
539 | <!-- manual-regeneration |
540 | cd listings/ch02-guessing-game-tutorial/listing-02-03/ | |
541 | cargo run | |
542 | 4 | |
543 | cargo run | |
544 | 5 | |
545 | --> | |
546 | ||
f035d41b | 547 | ```console |
13cf67c4 XL |
548 | $ cargo run |
549 | Compiling guessing_game v0.1.0 (file:///projects/guessing_game) | |
74b04a01 | 550 | Finished dev [unoptimized + debuginfo] target(s) in 2.53s |
13cf67c4 XL |
551 | Running `target/debug/guessing_game` |
552 | Guess the number! | |
553 | The secret number is: 7 | |
554 | Please input your guess. | |
555 | 4 | |
556 | You guessed: 4 | |
74b04a01 | 557 | |
13cf67c4 | 558 | $ cargo run |
74b04a01 | 559 | Finished dev [unoptimized + debuginfo] target(s) in 0.02s |
13cf67c4 XL |
560 | Running `target/debug/guessing_game` |
561 | Guess the number! | |
562 | The secret number is: 83 | |
563 | Please input your guess. | |
564 | 5 | |
565 | You guessed: 5 | |
566 | ``` | |
567 | ||
568 | You should get different random numbers, and they should all be numbers between | |
569 | 1 and 100. Great job! | |
570 | ||
571 | ## Comparing the Guess to the Secret Number | |
572 | ||
573 | Now that we have user input and a random number, we can compare them. That step | |
574 | is shown in Listing 2-4. Note that this code won’t compile quite yet, as we | |
575 | will explain. | |
576 | ||
577 | <span class="filename">Filename: src/main.rs</span> | |
578 | ||
579 | ```rust,ignore,does_not_compile | |
74b04a01 | 580 | {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-04/src/main.rs:here}} |
13cf67c4 XL |
581 | ``` |
582 | ||
583 | <span class="caption">Listing 2-4: Handling the possible return values of | |
584 | comparing two numbers</span> | |
585 | ||
3c0e092e XL |
586 | First we add another `use` statement, bringing a type called |
587 | `std::cmp::Ordering` into scope from the standard library. The `Ordering` type | |
588 | is another enum and has the variants `Less`, `Greater`, and `Equal`. These are | |
589 | the three outcomes that are possible when you compare two values. | |
13cf67c4 | 590 | |
69743fb6 XL |
591 | Then we add five new lines at the bottom that use the `Ordering` type. The |
592 | `cmp` method compares two values and can be called on anything that can be | |
13cf67c4 XL |
593 | compared. It takes a reference to whatever you want to compare with: here it’s |
594 | comparing the `guess` to the `secret_number`. Then it returns a variant of the | |
595 | `Ordering` enum we brought into scope with the `use` statement. We use a | |
596 | [`match`][match]<!-- ignore --> expression to decide what to do next based on | |
597 | which variant of `Ordering` was returned from the call to `cmp` with the values | |
598 | in `guess` and `secret_number`. | |
599 | ||
3c0e092e XL |
600 | A `match` expression is made up of *arms*. An arm consists of a *pattern* to |
601 | match against, and the code that should be run if the value given to `match` | |
602 | fits that arm’s pattern. Rust takes the value given to `match` and looks | |
603 | through each arm’s pattern in turn. Patterns and the `match` construct are | |
604 | powerful Rust features that let you express a variety of situations your code | |
605 | might encounter and make sure that you handle them all. These features will be | |
606 | covered in detail in Chapter 6 and Chapter 18, respectively. | |
607 | ||
608 | Let’s walk through an example with the `match` expression we use here. Say that | |
609 | the user has guessed 50 and the randomly generated secret number this time is | |
610 | 38. When the code compares 50 to 38, the `cmp` method will return | |
611 | `Ordering::Greater`, because 50 is greater than 38. The `match` expression gets | |
612 | the `Ordering::Greater` value and starts checking each arm’s pattern. It looks | |
613 | at the first arm’s pattern, `Ordering::Less`, and sees that the value | |
614 | `Ordering::Greater` does not match `Ordering::Less`, so it ignores the code in | |
615 | that arm and moves to the next arm. The next arm’s pattern is | |
616 | `Ordering::Greater`, which *does* match `Ordering::Greater`! The associated | |
617 | code in that arm will execute and print `Too big!` to the screen. The `match` | |
13cf67c4 XL |
618 | expression ends because it has no need to look at the last arm in this scenario. |
619 | ||
620 | However, the code in Listing 2-4 won’t compile yet. Let’s try it: | |
621 | ||
f035d41b | 622 | ```console |
74b04a01 | 623 | {{#include ../listings/ch02-guessing-game-tutorial/listing-02-04/output.txt}} |
13cf67c4 XL |
624 | ``` |
625 | ||
626 | The core of the error states that there are *mismatched types*. Rust has a | |
627 | strong, static type system. However, it also has type inference. When we wrote | |
9fa01778 | 628 | `let mut guess = String::new()`, Rust was able to infer that `guess` should be |
13cf67c4 | 629 | a `String` and didn’t make us write the type. The `secret_number`, on the other |
3c0e092e XL |
630 | hand, is a number type. A few of Rust’s number types can have a value between 1 |
631 | and 100: `i32`, a 32-bit number; `u32`, an unsigned 32-bit number; `i64`, a | |
a2a8927a | 632 | 64-bit number; as well as others. Unless otherwise specified, Rust defaults to |
3c0e092e XL |
633 | an `i32`, which is the type of `secret_number` unless you add type information |
634 | elsewhere that would cause Rust to infer a different numerical type. The reason | |
635 | for the error is that Rust cannot compare a string and a number type. | |
13cf67c4 XL |
636 | |
637 | Ultimately, we want to convert the `String` the program reads as input into a | |
3c0e092e XL |
638 | real number type so we can compare it numerically to the secret number. We do so |
639 | by adding this line to the `main` function body: | |
13cf67c4 XL |
640 | |
641 | <span class="filename">Filename: src/main.rs</span> | |
642 | ||
643 | ```rust,ignore | |
74b04a01 | 644 | {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/src/main.rs:here}} |
13cf67c4 XL |
645 | ``` |
646 | ||
f9f354fc | 647 | The line is: |
13cf67c4 XL |
648 | |
649 | ```rust,ignore | |
f9f354fc | 650 | let guess: u32 = guess.trim().parse().expect("Please type a number!"); |
13cf67c4 XL |
651 | ``` |
652 | ||
653 | We create a variable named `guess`. But wait, doesn’t the program already have | |
3c0e092e XL |
654 | a variable named `guess`? It does, but helpfully Rust allows us to *shadow* the |
655 | previous value of `guess` with a new one. Shadowing lets us reuse the `guess` | |
656 | variable name rather than forcing us to create two unique variables, such as | |
657 | `guess_str` and `guess` for example. We’ll cover this in more detail in Chapter | |
658 | 3, but for now know that this feature is often used when you want to convert a | |
659 | value from one type to another type. | |
660 | ||
661 | We bind this new variable to the expression `guess.trim().parse()`. The `guess` | |
662 | in the expression refers to the original `guess` variable that contained the | |
663 | input as a string. The `trim` method on a `String` instance will eliminate any | |
664 | whitespace at the beginning and end, which we must do to be able to compare the | |
665 | string to the `u32`, which can only contain numerical data. The user must press | |
666 | <span class="keystroke">enter</span> to satisfy `read_line` and input their | |
667 | guess, which adds a newline character to the string. For example, if the user | |
668 | types <span class="keystroke">5</span> and presses <span | |
669 | class="keystroke">enter</span>, `guess` looks like this: `5\n`. The `\n` | |
670 | represents “newline”. (On Windows, pressing <span | |
cdc7bbd5 XL |
671 | class="keystroke">enter</span> results in a carriage return and a newline, |
672 | `\r\n`). The `trim` method eliminates `\n` or `\r\n`, resulting in just `5`. | |
13cf67c4 XL |
673 | |
674 | The [`parse` method on strings][parse]<!-- ignore --> parses a string into some | |
675 | kind of number. Because this method can parse a variety of number types, we | |
676 | need to tell Rust the exact number type we want by using `let guess: u32`. The | |
677 | colon (`:`) after `guess` tells Rust we’ll annotate the variable’s type. Rust | |
678 | has a few built-in number types; the `u32` seen here is an unsigned, 32-bit | |
679 | integer. It’s a good default choice for a small positive number. You’ll learn | |
680 | about other number types in Chapter 3. Additionally, the `u32` annotation in | |
681 | this example program and the comparison with `secret_number` means that Rust | |
682 | will infer that `secret_number` should be a `u32` as well. So now the | |
683 | comparison will be between two values of the same type! | |
684 | ||
3c0e092e XL |
685 | The `parse` method will only work on characters that can logically be converted |
686 | into numbers and so can easily cause errors. If, for example, the string | |
13cf67c4 XL |
687 | contained `A👍%`, there would be no way to convert that to a number. Because it |
688 | might fail, the `parse` method returns a `Result` type, much as the `read_line` | |
9fa01778 XL |
689 | method does (discussed earlier in [“Handling Potential Failure with the |
690 | `Result` Type”](#handling-potential-failure-with-the-result-type)<!-- ignore | |
691 | -->). We’ll treat this `Result` the same way by using the `expect` method | |
13cf67c4 XL |
692 | again. If `parse` returns an `Err` `Result` variant because it couldn’t create |
693 | a number from the string, the `expect` call will crash the game and print the | |
694 | message we give it. If `parse` can successfully convert the string to a number, | |
695 | it will return the `Ok` variant of `Result`, and `expect` will return the | |
696 | number that we want from the `Ok` value. | |
697 | ||
698 | Let’s run the program now! | |
699 | ||
74b04a01 XL |
700 | <!-- manual-regeneration |
701 | cd listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/ | |
702 | cargo run | |
703 | 76 | |
704 | --> | |
705 | ||
f035d41b | 706 | ```console |
13cf67c4 XL |
707 | $ cargo run |
708 | Compiling guessing_game v0.1.0 (file:///projects/guessing_game) | |
74b04a01 | 709 | Finished dev [unoptimized + debuginfo] target(s) in 0.43s |
69743fb6 | 710 | Running `target/debug/guessing_game` |
13cf67c4 XL |
711 | Guess the number! |
712 | The secret number is: 58 | |
713 | Please input your guess. | |
714 | 76 | |
715 | You guessed: 76 | |
716 | Too big! | |
717 | ``` | |
718 | ||
719 | Nice! Even though spaces were added before the guess, the program still figured | |
720 | out that the user guessed 76. Run the program a few times to verify the | |
721 | different behavior with different kinds of input: guess the number correctly, | |
722 | guess a number that is too high, and guess a number that is too low. | |
723 | ||
724 | We have most of the game working now, but the user can make only one guess. | |
725 | Let’s change that by adding a loop! | |
726 | ||
727 | ## Allowing Multiple Guesses with Looping | |
728 | ||
3c0e092e | 729 | The `loop` keyword creates an infinite loop. We’ll add a loop to give users |
13cf67c4 XL |
730 | more chances at guessing the number: |
731 | ||
732 | <span class="filename">Filename: src/main.rs</span> | |
733 | ||
734 | ```rust,ignore | |
74b04a01 | 735 | {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/no-listing-04-looping/src/main.rs:here}} |
13cf67c4 XL |
736 | ``` |
737 | ||
3c0e092e XL |
738 | As you can see, we’ve moved everything from the guess input prompt onward into |
739 | a loop. Be sure to indent the lines inside the loop another four spaces each | |
740 | and run the program again. The program will now ask for another guess forever, | |
741 | which actually introduces a new problem. It doesn’t seem like the user can quit! | |
13cf67c4 | 742 | |
3c0e092e XL |
743 | The user could always interrupt the program by using the keyboard shortcut |
744 | <span class="keystroke">ctrl-c</span>. But there’s another way to escape this | |
9fa01778 XL |
745 | insatiable monster, as mentioned in the `parse` discussion in [“Comparing the |
746 | Guess to the Secret Number”](#comparing-the-guess-to-the-secret-number)<!-- | |
3c0e092e XL |
747 | ignore -->: if the user enters a non-number answer, the program will crash. We |
748 | can take advantage of that to allow the user to quit, as shown here: | |
13cf67c4 | 749 | |
74b04a01 XL |
750 | <!-- manual-regeneration |
751 | cd listings/ch02-guessing-game-tutorial/no-listing-04-looping/ | |
752 | cargo run | |
753 | (too small guess) | |
754 | (too big guess) | |
755 | (correct guess) | |
756 | quit | |
757 | --> | |
758 | ||
f035d41b | 759 | ```console |
13cf67c4 XL |
760 | $ cargo run |
761 | Compiling guessing_game v0.1.0 (file:///projects/guessing_game) | |
74b04a01 | 762 | Finished dev [unoptimized + debuginfo] target(s) in 1.50s |
69743fb6 | 763 | Running `target/debug/guessing_game` |
13cf67c4 XL |
764 | Guess the number! |
765 | The secret number is: 59 | |
766 | Please input your guess. | |
767 | 45 | |
768 | You guessed: 45 | |
769 | Too small! | |
770 | Please input your guess. | |
771 | 60 | |
772 | You guessed: 60 | |
773 | Too big! | |
774 | Please input your guess. | |
775 | 59 | |
776 | You guessed: 59 | |
777 | You win! | |
778 | Please input your guess. | |
779 | quit | |
fc512014 XL |
780 | thread 'main' panicked at 'Please type a number!: ParseIntError { kind: InvalidDigit }', src/main.rs:28:47 |
781 | note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace | |
13cf67c4 XL |
782 | ``` |
783 | ||
3c0e092e XL |
784 | Typing `quit` will quit the game, but as you’ll notice so will entering any |
785 | other non-number input. This is suboptimal to say the least; we want the game | |
786 | to also stop when the correct number is guessed. | |
13cf67c4 XL |
787 | |
788 | ### Quitting After a Correct Guess | |
789 | ||
790 | Let’s program the game to quit when the user wins by adding a `break` statement: | |
791 | ||
792 | <span class="filename">Filename: src/main.rs</span> | |
793 | ||
794 | ```rust,ignore | |
74b04a01 | 795 | {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/no-listing-05-quitting/src/main.rs:here}} |
13cf67c4 XL |
796 | ``` |
797 | ||
798 | Adding the `break` line after `You win!` makes the program exit the loop when | |
799 | the user guesses the secret number correctly. Exiting the loop also means | |
800 | exiting the program, because the loop is the last part of `main`. | |
801 | ||
802 | ### Handling Invalid Input | |
803 | ||
804 | To further refine the game’s behavior, rather than crashing the program when | |
805 | the user inputs a non-number, let’s make the game ignore a non-number so the | |
806 | user can continue guessing. We can do that by altering the line where `guess` | |
69743fb6 XL |
807 | is converted from a `String` to a `u32`, as shown in Listing 2-5. |
808 | ||
809 | <span class="filename">Filename: src/main.rs</span> | |
13cf67c4 XL |
810 | |
811 | ```rust,ignore | |
74b04a01 | 812 | {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-05/src/main.rs:here}} |
13cf67c4 XL |
813 | ``` |
814 | ||
69743fb6 XL |
815 | <span class="caption">Listing 2-5: Ignoring a non-number guess and asking for |
816 | another guess instead of crashing the program</span> | |
817 | ||
3c0e092e XL |
818 | We switch from an `expect` call to a `match` expression to move from crashing |
819 | on an error to handling the error. Remember that `parse` returns a `Result` | |
820 | type and `Result` is an enum that has the variants `Ok` or `Err`. We’re using a | |
821 | `match` expression here, as we did with the `Ordering` result of the `cmp` | |
822 | method. | |
13cf67c4 XL |
823 | |
824 | If `parse` is able to successfully turn the string into a number, it will | |
825 | return an `Ok` value that contains the resulting number. That `Ok` value will | |
826 | match the first arm’s pattern, and the `match` expression will just return the | |
827 | `num` value that `parse` produced and put inside the `Ok` value. That number | |
828 | will end up right where we want it in the new `guess` variable we’re creating. | |
829 | ||
830 | If `parse` is *not* able to turn the string into a number, it will return an | |
831 | `Err` value that contains more information about the error. The `Err` value | |
832 | does not match the `Ok(num)` pattern in the first `match` arm, but it does | |
833 | match the `Err(_)` pattern in the second arm. The underscore, `_`, is a | |
834 | catchall value; in this example, we’re saying we want to match all `Err` | |
835 | values, no matter what information they have inside them. So the program will | |
69743fb6 | 836 | execute the second arm’s code, `continue`, which tells the program to go to the |
9fa01778 | 837 | next iteration of the `loop` and ask for another guess. So, effectively, the |
69743fb6 | 838 | program ignores all errors that `parse` might encounter! |
13cf67c4 XL |
839 | |
840 | Now everything in the program should work as expected. Let’s try it: | |
841 | ||
74b04a01 XL |
842 | <!-- manual-regeneration |
843 | cd listings/ch02-guessing-game-tutorial/listing-02-05/ | |
844 | cargo run | |
845 | (too small guess) | |
846 | (too big guess) | |
847 | foo | |
848 | (correct guess) | |
849 | --> | |
850 | ||
f035d41b | 851 | ```console |
13cf67c4 XL |
852 | $ cargo run |
853 | Compiling guessing_game v0.1.0 (file:///projects/guessing_game) | |
fc512014 | 854 | Finished dev [unoptimized + debuginfo] target(s) in 4.45s |
69743fb6 | 855 | Running `target/debug/guessing_game` |
13cf67c4 XL |
856 | Guess the number! |
857 | The secret number is: 61 | |
858 | Please input your guess. | |
859 | 10 | |
860 | You guessed: 10 | |
861 | Too small! | |
862 | Please input your guess. | |
863 | 99 | |
864 | You guessed: 99 | |
865 | Too big! | |
866 | Please input your guess. | |
867 | foo | |
868 | Please input your guess. | |
869 | 61 | |
870 | You guessed: 61 | |
871 | You win! | |
872 | ``` | |
873 | ||
874 | Awesome! With one tiny final tweak, we will finish the guessing game. Recall | |
875 | that the program is still printing the secret number. That worked well for | |
876 | testing, but it ruins the game. Let’s delete the `println!` that outputs the | |
69743fb6 | 877 | secret number. Listing 2-6 shows the final code. |
13cf67c4 XL |
878 | |
879 | <span class="filename">Filename: src/main.rs</span> | |
880 | ||
881 | ```rust,ignore | |
74b04a01 | 882 | {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-06/src/main.rs}} |
13cf67c4 XL |
883 | ``` |
884 | ||
69743fb6 | 885 | <span class="caption">Listing 2-6: Complete guessing game code</span> |
13cf67c4 XL |
886 | |
887 | ## Summary | |
888 | ||
69743fb6 | 889 | At this point, you’ve successfully built the guessing game. Congratulations! |
13cf67c4 XL |
890 | |
891 | This project was a hands-on way to introduce you to many new Rust concepts: | |
136023e0 XL |
892 | `let`, `match`, functions, the use of external crates, and more. In the next |
893 | few chapters, you’ll learn about these concepts in more detail. Chapter 3 | |
894 | covers concepts that most programming languages have, such as variables, data | |
895 | types, and functions, and shows how to use them in Rust. Chapter 4 explores | |
896 | ownership, a feature that makes Rust different from other languages. Chapter 5 | |
897 | discusses structs and method syntax, and Chapter 6 explains how enums work. | |
9fa01778 | 898 | |
3c0e092e XL |
899 | [prelude]: ../std/prelude/index.html |
900 | [variables-and-mutability]: ch03-01-variables-and-mutability.html#variables-and-mutability | |
901 | [comments]: ch03-04-comments.html | |
902 | [string]: ../std/string/struct.String.html | |
903 | [iostdin]: ../std/io/struct.Stdin.html | |
904 | [read_line]: ../std/io/struct.Stdin.html#method.read_line | |
905 | [ioresult]: ../std/io/type.Result.html | |
906 | [result]: ../std/result/enum.Result.html | |
907 | [enums]: ch06-00-enums.html | |
908 | [expect]: ../std/result/enum.Result.html#method.expect | |
909 | [recover]: ch09-02-recoverable-errors-with-result.html | |
910 | [randcrate]: https://crates.io/crates/rand | |
911 | [semver]: http://semver.org | |
912 | [cratesio]: https://crates.io/ | |
913 | [doccargo]: http://doc.crates.io | |
914 | [doccratesio]: http://doc.crates.io/crates-io.html | |
915 | [match]: ch06-02-match.html | |
916 | [parse]: ../std/primitive.str.html#method.parse |