]> git.proxmox.com Git - rustc.git/blob - src/doc/book/guessing-game.md
New upstream version 1.16.0+dfsg1
[rustc.git] / src / doc / book / guessing-game.md
1 % Guessing Game
2
3 Let’s learn some Rust! For our first project, we’ll implement a classic
4 beginner programming problem: the guessing game. Here’s how it works: Our
5 program will generate a random integer between one and a hundred. It will then
6 prompt us to enter a guess. Upon entering our guess, it will tell us if we’re
7 too low or too high. Once we guess correctly, it will congratulate us. Sounds
8 good?
9
10 Along the way, we’ll learn a little bit about Rust. The next chapter, ‘Syntax
11 and Semantics’, will dive deeper into each part.
12
13 # Set up
14
15 Let’s set up a new project. Go to your projects directory. Remember how we had
16 to create our directory structure and a `Cargo.toml` for `hello_world`? Cargo
17 has a command that does that for us. Let’s give it a shot:
18
19 ```bash
20 $ cd ~/projects
21 $ cargo new guessing_game --bin
22 Created binary (application) `guessing_game` project
23 $ cd guessing_game
24 ```
25
26 We pass the name of our project to `cargo new`, and then the `--bin` flag,
27 since we’re making a binary, rather than a library.
28
29 Check out the generated `Cargo.toml`:
30
31 ```toml
32 [package]
33
34 name = "guessing_game"
35 version = "0.1.0"
36 authors = ["Your Name <you@example.com>"]
37 ```
38
39 Cargo gets this information from your environment. If it’s not correct, go ahead
40 and fix that.
41
42 Finally, Cargo generated a ‘Hello, world!’ for us. Check out `src/main.rs`:
43
44 ```rust
45 fn main() {
46 println!("Hello, world!");
47 }
48 ```
49
50 Let’s try compiling what Cargo gave us:
51
52 ```{bash}
53 $ cargo build
54 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
55 Finished debug [unoptimized + debuginfo] target(s) in 0.53 secs
56 ```
57
58 Excellent! Open up your `src/main.rs` again. We’ll be writing all of
59 our code in this file.
60
61 Remember the `run` command from last chapter? Try it out again here:
62
63 ```bash
64 $ cargo run
65 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
66 Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
67 Running `target/debug/guessing_game`
68 Hello, world!
69 ```
70
71 Great! Our game is just the kind of project `run` is good for: we need
72 to quickly test each iteration before moving on to the next one.
73
74 # Processing a Guess
75
76 Let’s get to it! The first thing we need to do for our guessing game is
77 allow our player to input a guess. Put this in your `src/main.rs`:
78
79 ```rust,no_run
80 use std::io;
81
82 fn main() {
83 println!("Guess the number!");
84
85 println!("Please input your guess.");
86
87 let mut guess = String::new();
88
89 io::stdin().read_line(&mut guess)
90 .expect("Failed to read line");
91
92 println!("You guessed: {}", guess);
93 }
94 ```
95
96 There’s a lot here! Let’s go over it, bit by bit.
97
98 ```rust,ignore
99 use std::io;
100 ```
101
102 We’ll need to take user input, and then print the result as output. As such, we
103 need the `io` library from the standard library. Rust only imports a few things
104 by default into every program, [the ‘prelude’][prelude]. If it’s not in the
105 prelude, you’ll have to `use` it directly. There is also a second ‘prelude’, the
106 [`io` prelude][ioprelude], which serves a similar function: you import it, and it
107 imports a number of useful, `io`-related things.
108
109 [prelude]: ../std/prelude/index.html
110 [ioprelude]: ../std/io/prelude/index.html
111
112 ```rust,ignore
113 fn main() {
114 ```
115
116 As you’ve seen before, the `main()` function is the entry point into your
117 program. The `fn` syntax declares a new function, the `()`s indicate that
118 there are no arguments, and `{` starts the body of the function. Because
119 we didn’t include a return type, it’s assumed to be `()`, an empty
120 [tuple][tuples].
121
122 [tuples]: primitive-types.html#tuples
123
124 ```rust,ignore
125 println!("Guess the number!");
126
127 println!("Please input your guess.");
128 ```
129
130 We previously learned that `println!()` is a [macro][macros] that
131 prints a [string][strings] to the screen.
132
133 [macros]: macros.html
134 [strings]: strings.html
135
136 ```rust,ignore
137 let mut guess = String::new();
138 ```
139
140 Now we’re getting interesting! There’s a lot going on in this little line.
141 The first thing to notice is that this is a [let statement][let], which is
142 used to create ‘variable bindings’. They take this form:
143
144 ```rust,ignore
145 let foo = bar;
146 ```
147
148 [let]: variable-bindings.html
149
150 This will create a new binding named `foo`, and bind it to the value `bar`. In
151 many languages, this is called a ‘variable’, but Rust’s variable bindings have
152 a few tricks up their sleeves.
153
154 For example, they’re [immutable][immutable] by default. That’s why our example
155 uses `mut`: it makes a binding mutable, rather than immutable. `let` doesn’t
156 take a name on the left hand side of the assignment, it actually accepts a
157 ‘[pattern][patterns]’. We’ll use patterns later. It’s easy enough
158 to use for now:
159
160 ```rust
161 let foo = 5; // `foo` is immutable.
162 let mut bar = 5; // `bar` is mutable.
163 ```
164
165 [immutable]: mutability.html
166 [patterns]: patterns.html
167
168 Oh, and `//` will start a comment, until the end of the line. Rust ignores
169 everything in [comments][comments].
170
171 [comments]: comments.html
172
173 So now we know that `let mut guess` will introduce a mutable binding named
174 `guess`, but we have to look at the other side of the `=` for what it’s
175 bound to: `String::new()`.
176
177 `String` is a string type, provided by the standard library. A
178 [`String`][string] is a growable, UTF-8 encoded bit of text.
179
180 [string]: ../std/string/struct.String.html
181
182 The `::new()` syntax uses `::` because this is an ‘associated function’ of
183 a particular type. That is to say, it’s associated with `String` itself,
184 rather than a particular instance of a `String`. Some languages call this a
185 ‘static method’.
186
187 This function is named `new()`, because it creates a new, empty `String`.
188 You’ll find a `new()` function on many types, as it’s a common name for making
189 a new value of some kind.
190
191 Let’s move forward:
192
193 ```rust,ignore
194 io::stdin().read_line(&mut guess)
195 .expect("Failed to read line");
196 ```
197
198 That’s a lot more! Let’s go bit-by-bit. The first line has two parts. Here’s
199 the first:
200
201 ```rust,ignore
202 io::stdin()
203 ```
204
205 Remember how we `use`d `std::io` on the first line of the program? We’re now
206 calling an associated function on it. If we didn’t `use std::io`, we could
207 have written this line as `std::io::stdin()`.
208
209 This particular function returns a handle to the standard input for your
210 terminal. More specifically, a [std::io::Stdin][iostdin].
211
212 [iostdin]: ../std/io/struct.Stdin.html
213
214 The next part will use this handle to get input from the user:
215
216 ```rust,ignore
217 .read_line(&mut guess)
218 ```
219
220 Here, we call the [`read_line()`][read_line] method on our handle.
221 [Methods][method] are like associated functions, but are only available on a
222 particular instance of a type, rather than the type itself. We’re also passing
223 one argument to `read_line()`: `&mut guess`.
224
225 [read_line]: ../std/io/struct.Stdin.html#method.read_line
226 [method]: method-syntax.html
227
228 Remember how we bound `guess` above? We said it was mutable. However,
229 `read_line` doesn’t take a `String` as an argument: it takes a `&mut String`.
230 Rust has a feature called ‘[references][references]’, which allows you to have
231 multiple references to one piece of data, which can reduce copying. References
232 are a complex feature, as one of Rust’s major selling points is how safe and
233 easy it is to use references. We don’t need to know a lot of those details to
234 finish our program right now, though. For now, all we need to know is that
235 like `let` bindings, references are immutable by default. Hence, we need to
236 write `&mut guess`, rather than `&guess`.
237
238 Why does `read_line()` take a mutable reference to a string? Its job is
239 to take what the user types into standard input, and place that into a
240 string. So it takes that string as an argument, and in order to add
241 the input, it needs to be mutable.
242
243 [references]: references-and-borrowing.html
244
245 But we’re not quite done with this line of code, though. While it’s
246 a single line of text, it’s only the first part of the single logical line of
247 code:
248
249 ```rust,ignore
250 .expect("Failed to read line");
251 ```
252
253 When you call a method with the `.foo()` syntax, you may introduce a newline
254 and other whitespace. This helps you split up long lines. We _could_ have
255 done:
256
257 ```rust,ignore
258 io::stdin().read_line(&mut guess).expect("failed to read line");
259 ```
260
261 But that gets hard to read. So we’ve split it up, two lines for two method
262 calls. We already talked about `read_line()`, but what about `expect()`? Well,
263 we already mentioned that `read_line()` puts what the user types into the `&mut
264 String` we pass it. But it also returns a value: in this case, an
265 [`io::Result`][ioresult]. Rust has a number of types named `Result` in its
266 standard library: a generic [`Result`][result], and then specific versions for
267 sub-libraries, like `io::Result`.
268
269 [ioresult]: ../std/io/type.Result.html
270 [result]: ../std/result/enum.Result.html
271
272 The purpose of these `Result` types is to encode error handling information.
273 Values of the `Result` type, like any type, have methods defined on them. In
274 this case, `io::Result` has an [`expect()` method][expect] that takes a value
275 it’s called on, and if it isn’t a successful one, [`panic!`][panic]s with a
276 message you passed it. A `panic!` like this will cause our program to crash,
277 displaying the message.
278
279 [expect]: ../std/result/enum.Result.html#method.expect
280 [panic]: error-handling.html
281
282 If we do not call `expect()`, our program will compile, but
283 we’ll get a warning:
284
285 ```bash
286 $ cargo build
287 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
288 warning: unused result which must be used, #[warn(unused_must_use)] on by default
289 --> src/main.rs:10:5
290 |
291 10 | io::stdin().read_line(&mut guess);
292 | ^
293
294 Finished debug [unoptimized + debuginfo] target(s) in 0.42 secs
295 ```
296
297 Rust warns us that we haven’t used the `Result` value. This warning comes from
298 a special annotation that `io::Result` has. Rust is trying to tell you that
299 you haven’t handled a possible error. The right way to suppress the error is
300 to actually write error handling. Luckily, if we want to crash if there’s
301 a problem, we can use `expect()`. If we can recover from the
302 error somehow, we’d do something else, but we’ll save that for a future
303 project.
304
305 There’s only one line of this first example left:
306
307 ```rust,ignore
308 println!("You guessed: {}", guess);
309 }
310 ```
311
312 This prints out the string we saved our input in. The `{}`s are a placeholder,
313 and so we pass it `guess` as an argument. If we had multiple `{}`s, we would
314 pass multiple arguments:
315
316 ```rust
317 let x = 5;
318 let y = 10;
319
320 println!("x and y: {} and {}", x, y);
321 ```
322
323 Easy.
324
325 Anyway, that’s the tour. We can run what we have with `cargo run`:
326
327 ```bash
328 $ cargo run
329 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
330 Finished debug [unoptimized + debuginfo] target(s) in 0.44 secs
331 Running `target/debug/guessing_game`
332 Guess the number!
333 Please input your guess.
334 6
335 You guessed: 6
336 ```
337
338 All right! Our first part is done: we can get input from the keyboard,
339 and then print it back out.
340
341 # Generating a secret number
342
343 Next, we need to generate a secret number. Rust does not yet include random
344 number functionality in its standard library. The Rust team does, however,
345 provide a [`rand` crate][randcrate]. A ‘crate’ is a package of Rust code.
346 We’ve been building a ‘binary crate’, which is an executable. `rand` is a
347 ‘library crate’, which contains code that’s intended to be used with other
348 programs.
349
350 [randcrate]: https://crates.io/crates/rand
351
352 Using external crates is where Cargo really shines. Before we can write
353 the code using `rand`, we need to modify our `Cargo.toml`. Open it up, and
354 add these few lines at the bottom:
355
356 ```toml
357 [dependencies]
358
359 rand="0.3.0"
360 ```
361
362 The `[dependencies]` section of `Cargo.toml` is like the `[package]` section:
363 everything that follows it is part of it, until the next section starts.
364 Cargo uses the dependencies section to know what dependencies on external
365 crates you have, and what versions you require. In this case, we’ve specified version `0.3.0`,
366 which Cargo understands to be any release that’s compatible with this specific version.
367 Cargo understands [Semantic Versioning][semver], which is a standard for writing version
368 numbers. A bare number like above is actually shorthand for `^0.3.0`,
369 meaning "anything compatible with 0.3.0".
370 If we wanted to use only `0.3.0` exactly, we could say `rand="=0.3.0"`
371 (note the two equal signs).
372 We could also use a range of versions.
373 [Cargo’s documentation][cargodoc] contains more details.
374
375 [semver]: http://semver.org
376 [cargodoc]: http://doc.crates.io/specifying-dependencies.html
377
378 Now, without changing any of our code, let’s build our project:
379
380 ```bash
381 $ cargo build
382 Updating registry `https://github.com/rust-lang/crates.io-index`
383 Downloading rand v0.3.14
384 Downloading libc v0.2.17
385 Compiling libc v0.2.17
386 Compiling rand v0.3.14
387 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
388 Finished debug [unoptimized + debuginfo] target(s) in 5.88 secs
389 ```
390
391 (You may see different versions, of course.)
392
393 Lots of new output! Now that we have an external dependency, Cargo fetches the
394 latest versions of everything from the registry, which is a copy of data from
395 [Crates.io][cratesio]. Crates.io is where people in the Rust ecosystem
396 post their open source Rust projects for others to use.
397
398 [cratesio]: https://crates.io
399
400 After updating the registry, Cargo checks our `[dependencies]` and downloads
401 any we don’t have yet. In this case, while we only said we wanted to depend on
402 `rand`, we’ve also grabbed a copy of `libc`. This is because `rand` depends on
403 `libc` to work. After downloading them, it compiles them, and then compiles
404 our project.
405
406 If we run `cargo build` again, we’ll get different output:
407
408 ```bash
409 $ cargo build
410 Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
411 ```
412
413 That’s right, nothing was done! Cargo knows that our project has been built, and that
414 all of its dependencies are built, and so there’s no reason to do all that
415 stuff. With nothing to do, it simply exits. If we open up `src/main.rs` again,
416 make a trivial change, and then save it again, we’ll only see two lines:
417
418 ```bash
419 $ cargo build
420 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
421 Finished debug [unoptimized + debuginfo] target(s) in 0.45 secs
422 ```
423
424 So, we told Cargo we wanted any `0.3.x` version of `rand`, and so it fetched the latest
425 version at the time this was written, `v0.3.14`. But what happens when next
426 week, version `v0.3.15` comes out, with an important bugfix? While getting
427 bugfixes is important, what if `0.3.15` contains a regression that breaks our
428 code?
429
430 The answer to this problem is the `Cargo.lock` file you’ll now find in your
431 project directory. When you build your project for the first time, Cargo
432 figures out all of the versions that fit your criteria, and then writes them
433 to the `Cargo.lock` file. When you build your project in the future, Cargo
434 will see that the `Cargo.lock` file exists, and then use that specific version
435 rather than do all the work of figuring out versions again. This lets you
436 have a repeatable build automatically. In other words, we’ll stay at `0.3.14`
437 until we explicitly upgrade, and so will anyone who we share our code with,
438 thanks to the lock file.
439
440 What about when we _do_ want to use `v0.3.15`? Cargo has another command,
441 `update`, which says ‘ignore the lock, figure out all the latest versions that
442 fit what we’ve specified. If that works, write those versions out to the lock
443 file’. But, by default, Cargo will only look for versions larger than `0.3.0`
444 and smaller than `0.4.0`. If we want to move to `0.4.x`, we’d have to update
445 the `Cargo.toml` directly. When we do, the next time we `cargo build`, Cargo
446 will update the index and re-evaluate our `rand` requirements.
447
448 There’s a lot more to say about [Cargo][doccargo] and [its
449 ecosystem][doccratesio], but for now, that’s all we need to know. Cargo makes
450 it really easy to re-use libraries, and so Rustaceans tend to write smaller
451 projects which are assembled out of a number of sub-packages.
452
453 [doccargo]: http://doc.crates.io
454 [doccratesio]: http://doc.crates.io/crates-io.html
455
456 Let’s get on to actually _using_ `rand`. Here’s our next step:
457
458 ```rust,ignore
459 extern crate rand;
460
461 use std::io;
462 use rand::Rng;
463
464 fn main() {
465 println!("Guess the number!");
466
467 let secret_number = rand::thread_rng().gen_range(1, 101);
468
469 println!("The secret number is: {}", secret_number);
470
471 println!("Please input your guess.");
472
473 let mut guess = String::new();
474
475 io::stdin().read_line(&mut guess)
476 .expect("failed to read line");
477
478 println!("You guessed: {}", guess);
479 }
480 ```
481
482 The first thing we’ve done is change the first line. It now says
483 `extern crate rand`. Because we declared `rand` in our `[dependencies]`, we
484 can use `extern crate` to let Rust know we’ll be making use of it. This also
485 does the equivalent of a `use rand;` as well, so we can make use of anything
486 in the `rand` crate by prefixing it with `rand::`.
487
488 Next, we added another `use` line: `use rand::Rng`. We’re going to use a
489 method in a moment, and it requires that `Rng` be in scope to work. The basic
490 idea is this: methods are defined on something called ‘traits’, and for the
491 method to work, it needs the trait to be in scope. For more about the
492 details, read the [traits][traits] section.
493
494 [traits]: traits.html
495
496 There are two other lines we added, in the middle:
497
498 ```rust,ignore
499 let secret_number = rand::thread_rng().gen_range(1, 101);
500
501 println!("The secret number is: {}", secret_number);
502 ```
503
504 We use the `rand::thread_rng()` function to get a copy of the random number
505 generator, which is local to the particular [thread][concurrency] of execution
506 we’re in. Because we `use rand::Rng`’d above, it has a `gen_range()` method
507 available. This method takes two arguments, and generates a number between
508 them. It’s inclusive on the lower bound, but exclusive on the upper bound,
509 so we need `1` and `101` to get a number ranging from one to a hundred.
510
511 [concurrency]: concurrency.html
512
513 The second line prints out the secret number. This is useful while
514 we’re developing our program, so we can easily test it out. But we’ll be
515 deleting it for the final version. It’s not much of a game if it prints out
516 the answer when you start it up!
517
518 Try running our new program a few times:
519
520 ```bash
521 $ cargo run
522 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
523 Finished debug [unoptimized + debuginfo] target(s) in 0.55 secs
524 Running `target/debug/guessing_game`
525 Guess the number!
526 The secret number is: 7
527 Please input your guess.
528 4
529 You guessed: 4
530 $ cargo run
531 Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
532 Running `target/debug/guessing_game`
533 Guess the number!
534 The secret number is: 83
535 Please input your guess.
536 5
537 You guessed: 5
538 ```
539
540 Great! Next up: comparing our guess to the secret number.
541
542 # Comparing guesses
543
544 Now that we’ve got user input, let’s compare our guess to the secret number.
545 Here’s our next step, though it doesn’t quite compile yet:
546
547 ```rust,ignore
548 extern crate rand;
549
550 use std::io;
551 use std::cmp::Ordering;
552 use rand::Rng;
553
554 fn main() {
555 println!("Guess the number!");
556
557 let secret_number = rand::thread_rng().gen_range(1, 101);
558
559 println!("The secret number is: {}", secret_number);
560
561 println!("Please input your guess.");
562
563 let mut guess = String::new();
564
565 io::stdin().read_line(&mut guess)
566 .expect("failed to read line");
567
568 println!("You guessed: {}", guess);
569
570 match guess.cmp(&secret_number) {
571 Ordering::Less => println!("Too small!"),
572 Ordering::Greater => println!("Too big!"),
573 Ordering::Equal => println!("You win!"),
574 }
575 }
576 ```
577
578 A few new bits here. The first is another `use`. We bring a type called
579 `std::cmp::Ordering` into scope. Then, five new lines at the bottom that use
580 it:
581
582 ```rust,ignore
583 match guess.cmp(&secret_number) {
584 Ordering::Less => println!("Too small!"),
585 Ordering::Greater => println!("Too big!"),
586 Ordering::Equal => println!("You win!"),
587 }
588 ```
589
590 The `cmp()` method can be called on anything that can be compared, and it
591 takes a reference to the thing you want to compare it to. It returns the
592 `Ordering` type we `use`d earlier. We use a [`match`][match] statement to
593 determine exactly what kind of `Ordering` it is. `Ordering` is an
594 [`enum`][enum], short for ‘enumeration’, which looks like this:
595
596 ```rust
597 enum Foo {
598 Bar,
599 Baz,
600 }
601 ```
602
603 [match]: match.html
604 [enum]: enums.html
605
606 With this definition, anything of type `Foo` can be either a
607 `Foo::Bar` or a `Foo::Baz`. We use the `::` to indicate the
608 namespace for a particular `enum` variant.
609
610 The [`Ordering`][ordering] `enum` has three possible variants: `Less`, `Equal`,
611 and `Greater`. The `match` statement takes a value of a type, and lets you
612 create an ‘arm’ for each possible value. Since we have three types of
613 `Ordering`, we have three arms:
614
615 ```rust,ignore
616 match guess.cmp(&secret_number) {
617 Ordering::Less => println!("Too small!"),
618 Ordering::Greater => println!("Too big!"),
619 Ordering::Equal => println!("You win!"),
620 }
621 ```
622
623 [ordering]: ../std/cmp/enum.Ordering.html
624
625 If it’s `Less`, we print `Too small!`, if it’s `Greater`, `Too big!`, and if
626 `Equal`, `You win!`. `match` is really useful, and is used often in Rust.
627
628 I did mention that this won’t quite compile yet, though. Let’s try it:
629
630 ```bash
631 $ cargo build
632 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
633 error[E0308]: mismatched types
634 --> src/main.rs:23:21
635 |
636 23 | match guess.cmp(&secret_number) {
637 | ^^^^^^^^^^^^^^ expected struct `std::string::String`, found integral variable
638 |
639 = note: expected type `&std::string::String`
640 = note: found type `&{integer}`
641
642 error: aborting due to previous error
643
644 error: Could not compile `guessing_game`.
645
646 To learn more, run the command again with --verbose.
647 ```
648
649 Whew! This is a big error. The core of it is that we have ‘mismatched types’.
650 Rust has a strong, static type system. However, it also has type inference.
651 When we wrote `let guess = String::new()`, Rust was able to infer that `guess`
652 should be a `String`, and so it doesn’t make us write out the type. And with
653 our `secret_number`, there are a number of types which can have a value
654 between one and a hundred: `i32`, a thirty-two-bit number, or `u32`, an
655 unsigned thirty-two-bit number, or `i64`, a sixty-four-bit number or others.
656 So far, that hasn’t mattered, and so Rust defaults to an `i32`. However, here,
657 Rust doesn’t know how to compare the `guess` and the `secret_number`. They
658 need to be the same type. Ultimately, we want to convert the `String` we
659 read as input into a real number type, for comparison. We can do that
660 with two more lines. Here’s our new program:
661
662 ```rust,ignore
663 extern crate rand;
664
665 use std::io;
666 use std::cmp::Ordering;
667 use rand::Rng;
668
669 fn main() {
670 println!("Guess the number!");
671
672 let secret_number = rand::thread_rng().gen_range(1, 101);
673
674 println!("The secret number is: {}", secret_number);
675
676 println!("Please input your guess.");
677
678 let mut guess = String::new();
679
680 io::stdin().read_line(&mut guess)
681 .expect("failed to read line");
682
683 let guess: u32 = guess.trim().parse()
684 .expect("Please type a number!");
685
686 println!("You guessed: {}", guess);
687
688 match guess.cmp(&secret_number) {
689 Ordering::Less => println!("Too small!"),
690 Ordering::Greater => println!("Too big!"),
691 Ordering::Equal => println!("You win!"),
692 }
693 }
694 ```
695
696 The new two lines:
697
698 ```rust,ignore
699 let guess: u32 = guess.trim().parse()
700 .expect("Please type a number!");
701 ```
702
703 Wait a minute, I thought we already had a `guess`? We do, but Rust allows us
704 to ‘shadow’ the previous `guess` with a new one. This is often used in this
705 exact situation, where `guess` starts as a `String`, but we want to convert it
706 to an `u32`. Shadowing lets us re-use the `guess` name, rather than forcing us
707 to come up with two unique names like `guess_str` and `guess`, or something
708 else.
709
710 We bind `guess` to an expression that looks like something we wrote earlier:
711
712 ```rust,ignore
713 guess.trim().parse()
714 ```
715
716 Here, `guess` refers to the old `guess`, the one that was a `String` with our
717 input in it. The `trim()` method on `String`s will eliminate any white space at
718 the beginning and end of our string. This is important, as we had to press the
719 ‘return’ key to satisfy `read_line()`. This means that if we type `5` and hit
720 return, `guess` looks like this: `5\n`. The `\n` represents ‘newline’, the
721 enter key. `trim()` gets rid of this, leaving our string with only the `5`. The
722 [`parse()` method on strings][parse] parses a string into some kind of number.
723 Since it can parse a variety of numbers, we need to give Rust a hint as to the
724 exact type of number we want. Hence, `let guess: u32`. The colon (`:`) after
725 `guess` tells Rust we’re going to annotate its type. `u32` is an unsigned,
726 thirty-two bit integer. Rust has [a number of built-in number types][number],
727 but we’ve chosen `u32`. It’s a good default choice for a small positive number.
728
729 [parse]: ../std/primitive.str.html#method.parse
730 [number]: primitive-types.html#numeric-types
731
732 Just like `read_line()`, our call to `parse()` could cause an error. What if
733 our string contained `A👍%`? There’d be no way to convert that to a number. As
734 such, we’ll do the same thing we did with `read_line()`: use the `expect()`
735 method to crash if there’s an error.
736
737 Let’s try our program out!
738
739 ```bash
740 $ cargo run
741 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
742 Finished debug [unoptimized + debuginfo] target(s) in 0.57 secs
743 Running `target/guessing_game`
744 Guess the number!
745 The secret number is: 58
746 Please input your guess.
747 76
748 You guessed: 76
749 Too big!
750 ```
751
752 Nice! You can see I even added spaces before my guess, and it still figured
753 out that I guessed 76. Run the program a few times, and verify that guessing
754 the number works, as well as guessing a number too small.
755
756 Now we’ve got most of the game working, but we can only make one guess. Let’s
757 change that by adding loops!
758
759 # Looping
760
761 The `loop` keyword gives us an infinite loop. Let’s add that in:
762
763 ```rust,ignore
764 extern crate rand;
765
766 use std::io;
767 use std::cmp::Ordering;
768 use rand::Rng;
769
770 fn main() {
771 println!("Guess the number!");
772
773 let secret_number = rand::thread_rng().gen_range(1, 101);
774
775 println!("The secret number is: {}", secret_number);
776
777 loop {
778 println!("Please input your guess.");
779
780 let mut guess = String::new();
781
782 io::stdin().read_line(&mut guess)
783 .expect("failed to read line");
784
785 let guess: u32 = guess.trim().parse()
786 .expect("Please type a number!");
787
788 println!("You guessed: {}", guess);
789
790 match guess.cmp(&secret_number) {
791 Ordering::Less => println!("Too small!"),
792 Ordering::Greater => println!("Too big!"),
793 Ordering::Equal => println!("You win!"),
794 }
795 }
796 }
797 ```
798
799 And try it out. But wait, didn’t we just add an infinite loop? Yup. Remember
800 our discussion about `parse()`? If we give a non-number answer, we’ll `panic!`
801 and quit. Observe:
802
803 ```bash
804 $ cargo run
805 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
806 Finished debug [unoptimized + debuginfo] target(s) in 0.58 secs
807 Running `target/guessing_game`
808 Guess the number!
809 The secret number is: 59
810 Please input your guess.
811 45
812 You guessed: 45
813 Too small!
814 Please input your guess.
815 60
816 You guessed: 60
817 Too big!
818 Please input your guess.
819 59
820 You guessed: 59
821 You win!
822 Please input your guess.
823 quit
824 thread 'main' panicked at 'Please type a number!'
825 ```
826
827 Ha! `quit` actually quits. As does any other non-number input. Well, this is
828 suboptimal to say the least. First, let’s actually quit when you win the game:
829
830 ```rust,ignore
831 extern crate rand;
832
833 use std::io;
834 use std::cmp::Ordering;
835 use rand::Rng;
836
837 fn main() {
838 println!("Guess the number!");
839
840 let secret_number = rand::thread_rng().gen_range(1, 101);
841
842 println!("The secret number is: {}", secret_number);
843
844 loop {
845 println!("Please input your guess.");
846
847 let mut guess = String::new();
848
849 io::stdin().read_line(&mut guess)
850 .expect("failed to read line");
851
852 let guess: u32 = guess.trim().parse()
853 .expect("Please type a number!");
854
855 println!("You guessed: {}", guess);
856
857 match guess.cmp(&secret_number) {
858 Ordering::Less => println!("Too small!"),
859 Ordering::Greater => println!("Too big!"),
860 Ordering::Equal => {
861 println!("You win!");
862 break;
863 }
864 }
865 }
866 }
867 ```
868
869 By adding the `break` line after the `You win!`, we’ll exit the loop when we
870 win. Exiting the loop also means exiting the program, since it’s the last
871 thing in `main()`. We have only one more tweak to make: when someone inputs a
872 non-number, we don’t want to quit, we want to ignore it. We can do that
873 like this:
874
875 ```rust,ignore
876 extern crate rand;
877
878 use std::io;
879 use std::cmp::Ordering;
880 use rand::Rng;
881
882 fn main() {
883 println!("Guess the number!");
884
885 let secret_number = rand::thread_rng().gen_range(1, 101);
886
887 println!("The secret number is: {}", secret_number);
888
889 loop {
890 println!("Please input your guess.");
891
892 let mut guess = String::new();
893
894 io::stdin().read_line(&mut guess)
895 .expect("failed to read line");
896
897 let guess: u32 = match guess.trim().parse() {
898 Ok(num) => num,
899 Err(_) => continue,
900 };
901
902 println!("You guessed: {}", guess);
903
904 match guess.cmp(&secret_number) {
905 Ordering::Less => println!("Too small!"),
906 Ordering::Greater => println!("Too big!"),
907 Ordering::Equal => {
908 println!("You win!");
909 break;
910 }
911 }
912 }
913 }
914 ```
915
916 These are the lines that changed:
917
918 ```rust,ignore
919 let guess: u32 = match guess.trim().parse() {
920 Ok(num) => num,
921 Err(_) => continue,
922 };
923 ```
924 This is how you generally move from ‘crash on error’ to ‘actually handle the
925 error’, by switching from `expect()` to a `match` statement. A `Result` is
926 returned by `parse()`, this is an `enum` like `Ordering`, but in this case,
927 each variant has some data associated with it: `Ok` is a success, and `Err` is a
928 failure. Each contains more information: the successfully parsed integer, or an
929 error type. In this case, we `match` on `Ok(num)`, which sets the name `num` to
930 the unwrapped `Ok` value (the integer), and then we return it on the
931 right-hand side. In the `Err` case, we don’t care what kind of error it is, so
932 we just use the catch all `_` instead of a name. This catches everything that
933 isn't `Ok`, and `continue` lets us move to the next iteration of the loop; in
934 effect, this enables us to ignore all errors and continue with our program.
935
936 Now we should be good! Let’s try:
937
938 ```bash
939 $ cargo run
940 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
941 Finished debug [unoptimized + debuginfo] target(s) in 0.57 secs
942 Running `target/guessing_game`
943 Guess the number!
944 The secret number is: 61
945 Please input your guess.
946 10
947 You guessed: 10
948 Too small!
949 Please input your guess.
950 99
951 You guessed: 99
952 Too big!
953 Please input your guess.
954 foo
955 Please input your guess.
956 61
957 You guessed: 61
958 You win!
959 ```
960
961 Awesome! With one tiny last tweak, we have finished the guessing game. Can you
962 think of what it is? That’s right, we don’t want to print out the secret
963 number. It was good for testing, but it kind of ruins the game. Here’s our
964 final source:
965
966 ```rust,ignore
967 extern crate rand;
968
969 use std::io;
970 use std::cmp::Ordering;
971 use rand::Rng;
972
973 fn main() {
974 println!("Guess the number!");
975
976 let secret_number = rand::thread_rng().gen_range(1, 101);
977
978 loop {
979 println!("Please input your guess.");
980
981 let mut guess = String::new();
982
983 io::stdin().read_line(&mut guess)
984 .expect("failed to read line");
985
986 let guess: u32 = match guess.trim().parse() {
987 Ok(num) => num,
988 Err(_) => continue,
989 };
990
991 println!("You guessed: {}", guess);
992
993 match guess.cmp(&secret_number) {
994 Ordering::Less => println!("Too small!"),
995 Ordering::Greater => println!("Too big!"),
996 Ordering::Equal => {
997 println!("You win!");
998 break;
999 }
1000 }
1001 }
1002 }
1003 ```
1004
1005 # Complete!
1006
1007 This project showed you a lot: `let`, `match`, methods, associated
1008 functions, using external crates, and more.
1009
1010 At this point, you have successfully built the Guessing Game! Congratulations!