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