]> git.proxmox.com Git - rustc.git/blob - src/doc/book/guessing-game.md
Imported Upstream version 1.9.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 $ cd guessing_game
23 ```
24
25 We pass the name of our project to `cargo new`, and then the `--bin` flag,
26 since we’re making a binary, rather than a library.
27
28 Check out the generated `Cargo.toml`:
29
30 ```toml
31 [package]
32
33 name = "guessing_game"
34 version = "0.1.0"
35 authors = ["Your Name <you@example.com>"]
36 ```
37
38 Cargo gets this information from your environment. If it’s not correct, go ahead
39 and fix that.
40
41 Finally, Cargo generated a ‘Hello, world!’ for us. Check out `src/main.rs`:
42
43 ```rust
44 fn main() {
45 println!("Hello, world!");
46 }
47 ```
48
49 Let’s try compiling what Cargo gave us:
50
51 ```{bash}
52 $ cargo build
53 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
54 ```
55
56 Excellent! Open up your `src/main.rs` again. We’ll be writing all of
57 our code in this file.
58
59 Before we move on, let me show you one more Cargo command: `run`. `cargo run`
60 is kind of like `cargo build`, but it also then runs the produced executable.
61 Try it out:
62
63 ```bash
64 $ cargo run
65 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
66 Running `target/debug/guessing_game`
67 Hello, world!
68 ```
69
70 Great! The `run` command comes in handy when you need to rapidly iterate on a
71 project. Our game is such a project, we need to quickly test each
72 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; // immutable.
162 let mut bar = 5; // 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 leave off calling this method, 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 src/main.rs:10:5: 10:39 warning: unused result which must be used,
289 #[warn(unused_must_use)] on by default
290 src/main.rs:10 io::stdin().read_line(&mut guess);
291 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
292 ```
293
294 Rust warns us that we haven’t used the `Result` value. This warning comes from
295 a special annotation that `io::Result` has. Rust is trying to tell you that
296 you haven’t handled a possible error. The right way to suppress the error is
297 to actually write error handling. Luckily, if we want to crash if there’s
298 a problem, we can use `expect()`. If we can recover from the
299 error somehow, we’d do something else, but we’ll save that for a future
300 project.
301
302 There’s only one line of this first example left:
303
304 ```rust,ignore
305 println!("You guessed: {}", guess);
306 }
307 ```
308
309 This prints out the string we saved our input in. The `{}`s are a placeholder,
310 and so we pass it `guess` as an argument. If we had multiple `{}`s, we would
311 pass multiple arguments:
312
313 ```rust
314 let x = 5;
315 let y = 10;
316
317 println!("x and y: {} and {}", x, y);
318 ```
319
320 Easy.
321
322 Anyway, that’s the tour. We can run what we have with `cargo run`:
323
324 ```bash
325 $ cargo run
326 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
327 Running `target/debug/guessing_game`
328 Guess the number!
329 Please input your guess.
330 6
331 You guessed: 6
332 ```
333
334 All right! Our first part is done: we can get input from the keyboard,
335 and then print it back out.
336
337 # Generating a secret number
338
339 Next, we need to generate a secret number. Rust does not yet include random
340 number functionality in its standard library. The Rust team does, however,
341 provide a [`rand` crate][randcrate]. A ‘crate’ is a package of Rust code.
342 We’ve been building a ‘binary crate’, which is an executable. `rand` is a
343 ‘library crate’, which contains code that’s intended to be used with other
344 programs.
345
346 [randcrate]: https://crates.io/crates/rand
347
348 Using external crates is where Cargo really shines. Before we can write
349 the code using `rand`, we need to modify our `Cargo.toml`. Open it up, and
350 add these few lines at the bottom:
351
352 ```toml
353 [dependencies]
354
355 rand="0.3.0"
356 ```
357
358 The `[dependencies]` section of `Cargo.toml` is like the `[package]` section:
359 everything that follows it is part of it, until the next section starts.
360 Cargo uses the dependencies section to know what dependencies on external
361 crates you have, and what versions you require. In this case, we’ve specified version `0.3.0`,
362 which Cargo understands to be any release that’s compatible with this specific version.
363 Cargo understands [Semantic Versioning][semver], which is a standard for writing version
364 numbers. A bare number like above is actually shorthand for `^0.3.0`,
365 meaning "anything compatible with 0.3.0".
366 If we wanted to use only `0.3.0` exactly, we could say `rand="=0.3.0"`
367 (note the two equal signs).
368 And if we wanted to use the latest version we could use `*`.
369 We could also use a range of versions.
370 [Cargo’s documentation][cargodoc] contains more details.
371
372 [semver]: http://semver.org
373 [cargodoc]: http://doc.crates.io/crates-io.html
374
375 Now, without changing any of our code, let’s build our project:
376
377 ```bash
378 $ cargo build
379 Updating registry `https://github.com/rust-lang/crates.io-index`
380 Downloading rand v0.3.8
381 Downloading libc v0.1.6
382 Compiling libc v0.1.6
383 Compiling rand v0.3.8
384 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
385 ```
386
387 (You may see different versions, of course.)
388
389 Lots of new output! Now that we have an external dependency, Cargo fetches the
390 latest versions of everything from the registry, which is a copy of data from
391 [Crates.io][cratesio]. Crates.io is where people in the Rust ecosystem
392 post their open source Rust projects for others to use.
393
394 [cratesio]: https://crates.io
395
396 After updating the registry, Cargo checks our `[dependencies]` and downloads
397 any we don’t have yet. In this case, while we only said we wanted to depend on
398 `rand`, we’ve also grabbed a copy of `libc`. This is because `rand` depends on
399 `libc` to work. After downloading them, it compiles them, and then compiles
400 our project.
401
402 If we run `cargo build` again, we’ll get different output:
403
404 ```bash
405 $ cargo build
406 ```
407
408 That’s right, no output! Cargo knows that our project has been built, and that
409 all of its dependencies are built, and so there’s no reason to do all that
410 stuff. With nothing to do, it simply exits. If we open up `src/main.rs` again,
411 make a trivial change, and then save it again, we’ll only see one line:
412
413 ```bash
414 $ cargo build
415 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
416 ```
417
418 So, we told Cargo we wanted any `0.3.x` version of `rand`, and so it fetched the latest
419 version at the time this was written, `v0.3.8`. But what happens when next
420 week, version `v0.3.9` comes out, with an important bugfix? While getting
421 bugfixes is important, what if `0.3.9` contains a regression that breaks our
422 code?
423
424 The answer to this problem is the `Cargo.lock` file you’ll now find in your
425 project directory. When you build your project for the first time, Cargo
426 figures out all of the versions that fit your criteria, and then writes them
427 to the `Cargo.lock` file. When you build your project in the future, Cargo
428 will see that the `Cargo.lock` file exists, and then use that specific version
429 rather than do all the work of figuring out versions again. This lets you
430 have a repeatable build automatically. In other words, we’ll stay at `0.3.8`
431 until we explicitly upgrade, and so will anyone who we share our code with,
432 thanks to the lock file.
433
434 What about when we _do_ want to use `v0.3.9`? Cargo has another command,
435 `update`, which says ‘ignore the lock, figure out all the latest versions that
436 fit what we’ve specified. If that works, write those versions out to the lock
437 file’. But, by default, Cargo will only look for versions larger than `0.3.0`
438 and smaller than `0.4.0`. If we want to move to `0.4.x`, we’d have to update
439 the `Cargo.toml` directly. When we do, the next time we `cargo build`, Cargo
440 will update the index and re-evaluate our `rand` requirements.
441
442 There’s a lot more to say about [Cargo][doccargo] and [its
443 ecosystem][doccratesio], but for now, that’s all we need to know. Cargo makes
444 it really easy to re-use libraries, and so Rustaceans tend to write smaller
445 projects which are assembled out of a number of sub-packages.
446
447 [doccargo]: http://doc.crates.io
448 [doccratesio]: http://doc.crates.io/crates-io.html
449
450 Let’s get on to actually _using_ `rand`. Here’s our next step:
451
452 ```rust,ignore
453 extern crate rand;
454
455 use std::io;
456 use rand::Rng;
457
458 fn main() {
459 println!("Guess the number!");
460
461 let secret_number = rand::thread_rng().gen_range(1, 101);
462
463 println!("The secret number is: {}", secret_number);
464
465 println!("Please input your guess.");
466
467 let mut guess = String::new();
468
469 io::stdin().read_line(&mut guess)
470 .expect("failed to read line");
471
472 println!("You guessed: {}", guess);
473 }
474 ```
475
476 The first thing we’ve done is change the first line. It now says
477 `extern crate rand`. Because we declared `rand` in our `[dependencies]`, we
478 can use `extern crate` to let Rust know we’ll be making use of it. This also
479 does the equivalent of a `use rand;` as well, so we can make use of anything
480 in the `rand` crate by prefixing it with `rand::`.
481
482 Next, we added another `use` line: `use rand::Rng`. We’re going to use a
483 method in a moment, and it requires that `Rng` be in scope to work. The basic
484 idea is this: methods are defined on something called ‘traits’, and for the
485 method to work, it needs the trait to be in scope. For more about the
486 details, read the [traits][traits] section.
487
488 [traits]: traits.html
489
490 There are two other lines we added, in the middle:
491
492 ```rust,ignore
493 let secret_number = rand::thread_rng().gen_range(1, 101);
494
495 println!("The secret number is: {}", secret_number);
496 ```
497
498 We use the `rand::thread_rng()` function to get a copy of the random number
499 generator, which is local to the particular [thread][concurrency] of execution
500 we’re in. Because we `use rand::Rng`’d above, it has a `gen_range()` method
501 available. This method takes two arguments, and generates a number between
502 them. It’s inclusive on the lower bound, but exclusive on the upper bound,
503 so we need `1` and `101` to get a number ranging from one to a hundred.
504
505 [concurrency]: concurrency.html
506
507 The second line prints out the secret number. This is useful while
508 we’re developing our program, so we can easily test it out. But we’ll be
509 deleting it for the final version. It’s not much of a game if it prints out
510 the answer when you start it up!
511
512 Try running our new program a few times:
513
514 ```bash
515 $ cargo run
516 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
517 Running `target/debug/guessing_game`
518 Guess the number!
519 The secret number is: 7
520 Please input your guess.
521 4
522 You guessed: 4
523 $ cargo run
524 Running `target/debug/guessing_game`
525 Guess the number!
526 The secret number is: 83
527 Please input your guess.
528 5
529 You guessed: 5
530 ```
531
532 Great! Next up: comparing our guess to the secret number.
533
534 # Comparing guesses
535
536 Now that we’ve got user input, let’s compare our guess to the secret number.
537 Here’s our next step, though it doesn’t quite compile yet:
538
539 ```rust,ignore
540 extern crate rand;
541
542 use std::io;
543 use std::cmp::Ordering;
544 use rand::Rng;
545
546 fn main() {
547 println!("Guess the number!");
548
549 let secret_number = rand::thread_rng().gen_range(1, 101);
550
551 println!("The secret number is: {}", secret_number);
552
553 println!("Please input your guess.");
554
555 let mut guess = String::new();
556
557 io::stdin().read_line(&mut guess)
558 .expect("failed to read line");
559
560 println!("You guessed: {}", guess);
561
562 match guess.cmp(&secret_number) {
563 Ordering::Less => println!("Too small!"),
564 Ordering::Greater => println!("Too big!"),
565 Ordering::Equal => println!("You win!"),
566 }
567 }
568 ```
569
570 A few new bits here. The first is another `use`. We bring a type called
571 `std::cmp::Ordering` into scope. Then, five new lines at the bottom that use
572 it:
573
574 ```rust,ignore
575 match guess.cmp(&secret_number) {
576 Ordering::Less => println!("Too small!"),
577 Ordering::Greater => println!("Too big!"),
578 Ordering::Equal => println!("You win!"),
579 }
580 ```
581
582 The `cmp()` method can be called on anything that can be compared, and it
583 takes a reference to the thing you want to compare it to. It returns the
584 `Ordering` type we `use`d earlier. We use a [`match`][match] statement to
585 determine exactly what kind of `Ordering` it is. `Ordering` is an
586 [`enum`][enum], short for ‘enumeration’, which looks like this:
587
588 ```rust
589 enum Foo {
590 Bar,
591 Baz,
592 }
593 ```
594
595 [match]: match.html
596 [enum]: enums.html
597
598 With this definition, anything of type `Foo` can be either a
599 `Foo::Bar` or a `Foo::Baz`. We use the `::` to indicate the
600 namespace for a particular `enum` variant.
601
602 The [`Ordering`][ordering] `enum` has three possible variants: `Less`, `Equal`,
603 and `Greater`. The `match` statement takes a value of a type, and lets you
604 create an ‘arm’ for each possible value. Since we have three types of
605 `Ordering`, we have three arms:
606
607 ```rust,ignore
608 match guess.cmp(&secret_number) {
609 Ordering::Less => println!("Too small!"),
610 Ordering::Greater => println!("Too big!"),
611 Ordering::Equal => println!("You win!"),
612 }
613 ```
614
615 [ordering]: ../std/cmp/enum.Ordering.html
616
617 If it’s `Less`, we print `Too small!`, if it’s `Greater`, `Too big!`, and if
618 `Equal`, `You win!`. `match` is really useful, and is used often in Rust.
619
620 I did mention that this won’t quite compile yet, though. Let’s try it:
621
622 ```bash
623 $ cargo build
624 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
625 src/main.rs:28:21: 28:35 error: mismatched types:
626 expected `&collections::string::String`,
627 found `&_`
628 (expected struct `collections::string::String`,
629 found integral variable) [E0308]
630 src/main.rs:28 match guess.cmp(&secret_number) {
631 ^~~~~~~~~~~~~~
632 error: aborting due to previous error
633 Could not compile `guessing_game`.
634 ```
635
636 Whew! This is a big error. The core of it is that we have ‘mismatched types’.
637 Rust has a strong, static type system. However, it also has type inference.
638 When we wrote `let guess = String::new()`, Rust was able to infer that `guess`
639 should be a `String`, and so it doesn’t make us write out the type. And with
640 our `secret_number`, there are a number of types which can have a value
641 between one and a hundred: `i32`, a thirty-two-bit number, or `u32`, an
642 unsigned thirty-two-bit number, or `i64`, a sixty-four-bit number or others.
643 So far, that hasn’t mattered, and so Rust defaults to an `i32`. However, here,
644 Rust doesn’t know how to compare the `guess` and the `secret_number`. They
645 need to be the same type. Ultimately, we want to convert the `String` we
646 read as input into a real number type, for comparison. We can do that
647 with two more lines. Here’s our new program:
648
649 ```rust,ignore
650 extern crate rand;
651
652 use std::io;
653 use std::cmp::Ordering;
654 use rand::Rng;
655
656 fn main() {
657 println!("Guess the number!");
658
659 let secret_number = rand::thread_rng().gen_range(1, 101);
660
661 println!("The secret number is: {}", secret_number);
662
663 println!("Please input your guess.");
664
665 let mut guess = String::new();
666
667 io::stdin().read_line(&mut guess)
668 .expect("failed to read line");
669
670 let guess: u32 = guess.trim().parse()
671 .expect("Please type a number!");
672
673 println!("You guessed: {}", guess);
674
675 match guess.cmp(&secret_number) {
676 Ordering::Less => println!("Too small!"),
677 Ordering::Greater => println!("Too big!"),
678 Ordering::Equal => println!("You win!"),
679 }
680 }
681 ```
682
683 The new two lines:
684
685 ```rust,ignore
686 let guess: u32 = guess.trim().parse()
687 .expect("Please type a number!");
688 ```
689
690 Wait a minute, I thought we already had a `guess`? We do, but Rust allows us
691 to ‘shadow’ the previous `guess` with a new one. This is often used in this
692 exact situation, where `guess` starts as a `String`, but we want to convert it
693 to an `u32`. Shadowing lets us re-use the `guess` name, rather than forcing us
694 to come up with two unique names like `guess_str` and `guess`, or something
695 else.
696
697 We bind `guess` to an expression that looks like something we wrote earlier:
698
699 ```rust,ignore
700 guess.trim().parse()
701 ```
702
703 Here, `guess` refers to the old `guess`, the one that was a `String` with our
704 input in it. The `trim()` method on `String`s will eliminate any white space at
705 the beginning and end of our string. This is important, as we had to press the
706 ‘return’ key to satisfy `read_line()`. This means that if we type `5` and hit
707 return, `guess` looks like this: `5\n`. The `\n` represents ‘newline’, the
708 enter key. `trim()` gets rid of this, leaving our string with only the `5`. The
709 [`parse()` method on strings][parse] parses a string into some kind of number.
710 Since it can parse a variety of numbers, we need to give Rust a hint as to the
711 exact type of number we want. Hence, `let guess: u32`. The colon (`:`) after
712 `guess` tells Rust we’re going to annotate its type. `u32` is an unsigned,
713 thirty-two bit integer. Rust has [a number of built-in number types][number],
714 but we’ve chosen `u32`. It’s a good default choice for a small positive number.
715
716 [parse]: ../std/primitive.str.html#method.parse
717 [number]: primitive-types.html#numeric-types
718
719 Just like `read_line()`, our call to `parse()` could cause an error. What if
720 our string contained `A👍%`? There’d be no way to convert that to a number. As
721 such, we’ll do the same thing we did with `read_line()`: use the `expect()`
722 method to crash if there’s an error.
723
724 Let’s try our program out!
725
726 ```bash
727 $ cargo run
728 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
729 Running `target/guessing_game`
730 Guess the number!
731 The secret number is: 58
732 Please input your guess.
733 76
734 You guessed: 76
735 Too big!
736 ```
737
738 Nice! You can see I even added spaces before my guess, and it still figured
739 out that I guessed 76. Run the program a few times, and verify that guessing
740 the number works, as well as guessing a number too small.
741
742 Now we’ve got most of the game working, but we can only make one guess. Let’s
743 change that by adding loops!
744
745 # Looping
746
747 The `loop` keyword gives us an infinite loop. Let’s add that in:
748
749 ```rust,ignore
750 extern crate rand;
751
752 use std::io;
753 use std::cmp::Ordering;
754 use rand::Rng;
755
756 fn main() {
757 println!("Guess the number!");
758
759 let secret_number = rand::thread_rng().gen_range(1, 101);
760
761 println!("The secret number is: {}", secret_number);
762
763 loop {
764 println!("Please input your guess.");
765
766 let mut guess = String::new();
767
768 io::stdin().read_line(&mut guess)
769 .expect("failed to read line");
770
771 let guess: u32 = guess.trim().parse()
772 .expect("Please type a number!");
773
774 println!("You guessed: {}", guess);
775
776 match guess.cmp(&secret_number) {
777 Ordering::Less => println!("Too small!"),
778 Ordering::Greater => println!("Too big!"),
779 Ordering::Equal => println!("You win!"),
780 }
781 }
782 }
783 ```
784
785 And try it out. But wait, didn’t we just add an infinite loop? Yup. Remember
786 our discussion about `parse()`? If we give a non-number answer, we’ll `panic!`
787 and quit. Observe:
788
789 ```bash
790 $ cargo run
791 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
792 Running `target/guessing_game`
793 Guess the number!
794 The secret number is: 59
795 Please input your guess.
796 45
797 You guessed: 45
798 Too small!
799 Please input your guess.
800 60
801 You guessed: 60
802 Too big!
803 Please input your guess.
804 59
805 You guessed: 59
806 You win!
807 Please input your guess.
808 quit
809 thread '<main>' panicked at 'Please type a number!'
810 ```
811
812 Ha! `quit` actually quits. As does any other non-number input. Well, this is
813 suboptimal to say the least. First, let’s actually quit when you win the game:
814
815 ```rust,ignore
816 extern crate rand;
817
818 use std::io;
819 use std::cmp::Ordering;
820 use rand::Rng;
821
822 fn main() {
823 println!("Guess the number!");
824
825 let secret_number = rand::thread_rng().gen_range(1, 101);
826
827 println!("The secret number is: {}", secret_number);
828
829 loop {
830 println!("Please input your guess.");
831
832 let mut guess = String::new();
833
834 io::stdin().read_line(&mut guess)
835 .expect("failed to read line");
836
837 let guess: u32 = guess.trim().parse()
838 .expect("Please type a number!");
839
840 println!("You guessed: {}", guess);
841
842 match guess.cmp(&secret_number) {
843 Ordering::Less => println!("Too small!"),
844 Ordering::Greater => println!("Too big!"),
845 Ordering::Equal => {
846 println!("You win!");
847 break;
848 }
849 }
850 }
851 }
852 ```
853
854 By adding the `break` line after the `You win!`, we’ll exit the loop when we
855 win. Exiting the loop also means exiting the program, since it’s the last
856 thing in `main()`. We have only one more tweak to make: when someone inputs a
857 non-number, we don’t want to quit, we want to ignore it. We can do that
858 like this:
859
860 ```rust,ignore
861 extern crate rand;
862
863 use std::io;
864 use std::cmp::Ordering;
865 use rand::Rng;
866
867 fn main() {
868 println!("Guess the number!");
869
870 let secret_number = rand::thread_rng().gen_range(1, 101);
871
872 println!("The secret number is: {}", secret_number);
873
874 loop {
875 println!("Please input your guess.");
876
877 let mut guess = String::new();
878
879 io::stdin().read_line(&mut guess)
880 .expect("failed to read line");
881
882 let guess: u32 = match guess.trim().parse() {
883 Ok(num) => num,
884 Err(_) => continue,
885 };
886
887 println!("You guessed: {}", guess);
888
889 match guess.cmp(&secret_number) {
890 Ordering::Less => println!("Too small!"),
891 Ordering::Greater => println!("Too big!"),
892 Ordering::Equal => {
893 println!("You win!");
894 break;
895 }
896 }
897 }
898 }
899 ```
900
901 These are the lines that changed:
902
903 ```rust,ignore
904 let guess: u32 = match guess.trim().parse() {
905 Ok(num) => num,
906 Err(_) => continue,
907 };
908 ```
909 This is how you generally move from ‘crash on error’ to ‘actually handle the
910 error’, by switching from `expect()` to a `match` statement. A `Result` is
911 returned by `parse()`, this is an `enum` like `Ordering`, but in this case,
912 each variant has some data associated with it: `Ok` is a success, and `Err` is a
913 failure. Each contains more information: the successfully parsed integer, or an
914 error type. In this case, we `match` on `Ok(num)`, which sets the name `num` to
915 the unwrapped `Ok` value (the integer), and then we return it on the
916 right-hand side. In the `Err` case, we don’t care what kind of error it is, so
917 we just use the catch all `_` instead of a name. This catches everything that
918 isn't `Ok`, and `continue` lets us move to the next iteration of the loop; in
919 effect, this enables us to ignore all errors and continue with our program.
920
921 Now we should be good! Let’s try:
922
923 ```bash
924 $ cargo run
925 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
926 Running `target/guessing_game`
927 Guess the number!
928 The secret number is: 61
929 Please input your guess.
930 10
931 You guessed: 10
932 Too small!
933 Please input your guess.
934 99
935 You guessed: 99
936 Too big!
937 Please input your guess.
938 foo
939 Please input your guess.
940 61
941 You guessed: 61
942 You win!
943 ```
944
945 Awesome! With one tiny last tweak, we have finished the guessing game. Can you
946 think of what it is? That’s right, we don’t want to print out the secret
947 number. It was good for testing, but it kind of ruins the game. Here’s our
948 final source:
949
950 ```rust,ignore
951 extern crate rand;
952
953 use std::io;
954 use std::cmp::Ordering;
955 use rand::Rng;
956
957 fn main() {
958 println!("Guess the number!");
959
960 let secret_number = rand::thread_rng().gen_range(1, 101);
961
962 loop {
963 println!("Please input your guess.");
964
965 let mut guess = String::new();
966
967 io::stdin().read_line(&mut guess)
968 .expect("failed to read line");
969
970 let guess: u32 = match guess.trim().parse() {
971 Ok(num) => num,
972 Err(_) => continue,
973 };
974
975 println!("You guessed: {}", guess);
976
977 match guess.cmp(&secret_number) {
978 Ordering::Less => println!("Too small!"),
979 Ordering::Greater => println!("Too big!"),
980 Ordering::Equal => {
981 println!("You win!");
982 break;
983 }
984 }
985 }
986 }
987 ```
988
989 # Complete!
990
991 At this point, you have successfully built the Guessing Game! Congratulations!
992
993 This first project showed you a lot: `let`, `match`, methods, associated
994 functions, using external crates, and more. Our next project will show off
995 even more.