Skip to content

Commit e76369e

Browse files
committed
auto merge of #15229 : steveklabnik/rust/if, r=cmr
Whew. So much here! Feedback very welcome. This is the first part where we actually start learning things. I'd like to think I struck a good balance of explaining enough details, without getting too bogged down, and without being confusing... but of course I'd think that. 😉 As I mention in the commit comment, We probably want to move the guessing game to the rust-lang org, rather than just having it on my GitHub. Or, I could put the code inline. I think it'd be neat to have it as a project, so people can pull it down with Cargo. Until we make that decision, I'll just leave this here.
2 parents 3806575 + a55c508 commit e76369e

File tree

1 file changed

+221
-10
lines changed

1 file changed

+221
-10
lines changed

src/doc/guide.md

Lines changed: 221 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -413,23 +413,209 @@ rest of your Rust career.
413413
Next, we'll learn more about Rust itself, by starting to write a more complicated
414414
program. We hope you want to do more with Rust than just print "Hello, world!"
415415

416-
## If
416+
## Guessing Game
417417

418-
## Functions
418+
Let's write a bigger program in Rust. We could just go through a laundry list
419+
of Rust features, but that's boring. Instead, we'll learn more about how to
420+
code in Rust by writing a few example projects.
419421

420-
return
422+
For our first project, we'll implement a classic beginner programming problem:
423+
the guessing game. Here's how it works: Our program will generate a random
424+
integer between one and a hundred. It will then prompt us to enter a guess.
425+
Upon entering our guess, it will tell us if we're too low or too high. Once we
426+
guess correctly, it will congratulate us, and print the number of guesses we've
427+
taken to the screen. Sound good? It sounds easy, but it'll end up showing off a
428+
number of basic features of Rust.
421429

422-
comments
430+
### Set up
423431

424-
## Testing
432+
Let's set up a new project. Go to your projects directory, and make a new
433+
directory for the project, as well as a `src` directory for our code:
425434

426-
attributes
435+
```{bash}
436+
$ cd ~/projects
437+
$ mkdir guessing_game
438+
$ cd guessing_game
439+
$ mkdir src
440+
```
427441

428-
stability markers
442+
Great. Next, let's make a `Cargo.toml` file so Cargo knows how to build our
443+
project:
429444

430-
## Crates and Modules
445+
```{ignore}
446+
[package]
431447
432-
visibility
448+
name = "guessing_game"
449+
version = "0.1.0"
450+
authors = [ "[email protected]" ]
451+
452+
[[bin]]
453+
454+
name = "guessing_game"
455+
```
456+
457+
Finally, we need our source file. Let's just make it hello world for now, so we
458+
can check that our setup works. In `src/guessing_game.rs`:
459+
460+
```{rust}
461+
fn main() {
462+
println!("Hello world!");
463+
}
464+
```
465+
466+
Let's make sure that worked:
467+
468+
```{bash}
469+
$ cargo build
470+
Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
471+
$
472+
```
473+
474+
Excellent! Open up your `src/guessing_game.rs` again. We'll be writing all of
475+
our code in this file. The next section of the tutorial will show you how to
476+
build multiple-file projects.
477+
478+
## Variable bindings
479+
480+
The first thing we'll learn about are 'variable bindings.' They look like this:
481+
482+
```{rust}
483+
let x = 5i;
484+
```
485+
486+
In many languages, this is called a 'variable.' But Rust's variable bindings
487+
have a few tricks up their sleeves. Rust has a very powerful feature called
488+
'pattern matching' that we'll get into detail with later, but the left
489+
hand side of a `let` expression is a full pattern, not just a variable name.
490+
This means we can do things like:
491+
492+
```{rust}
493+
let (x, y) = (1i, 2i);
494+
```
495+
496+
After this expression is evaluated, `x` will be one, and `y` will be two.
497+
Patterns are really powerful, but this is about all we can do with them so far.
498+
So let's just keep this in the back of our minds as we go forward.
499+
500+
By the way, in these examples, `i` indicates that the number is an integer.
501+
502+
Rust is a statically typed language, which means that we specify our types up
503+
front. So why does our first example compile? Well, Rust has this thing called
504+
"[Hindley-Milner type
505+
inference](http://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system)",
506+
named after some really smart type theorists. If you clicked that link, don't
507+
be scared: what this means for you is that Rust will attempt to infer the types
508+
in your program, and it's pretty good at it. If it can infer the type, Rust
509+
doesn't require you to actually type it out.
510+
511+
We can add the type if we want to. Types come after a colon (`:`):
512+
513+
```{rust}
514+
let x: int = 5;
515+
```
516+
517+
If I asked you to read this out loud to the rest of the class, you'd say "`x`
518+
is a binding with the type `int` and the value `five`." Rust requires you to
519+
initialize the binding with a value before you're allowed to use it. If
520+
we try...
521+
522+
```{ignore}
523+
let x;
524+
```
525+
526+
...we'll get an error:
527+
528+
```{ignore}
529+
src/guessing_game.rs:2:9: 2:10 error: cannot determine a type for this local variable: unconstrained type
530+
src/guessing_game.rs:2 let x;
531+
^
532+
```
533+
534+
Giving it a type will compile, though:
535+
536+
```{ignore}
537+
let x: int;
538+
```
539+
540+
Let's try it out. Change your `src/guessing_game.rs` file to look like this:
541+
542+
```{rust}
543+
fn main() {
544+
let x: int;
545+
546+
println!("Hello world!");
547+
}
548+
```
549+
550+
You can use `cargo build` on the command line to build it. You'll get a warning,
551+
but it will still print "Hello, world!":
552+
553+
```{ignore,notrust}
554+
Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
555+
src/guessing_game.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variable)] on by default
556+
src/guessing_game.rs:2 let x: int;
557+
^
558+
```
559+
560+
Rust warns us that we never use the variable binding, but since we never use it,
561+
no harm, no foul. Things change if we try to actually use this `x`, however. Let's
562+
do that. Change your program to look like this:
563+
564+
```{rust,ignore}
565+
fn main() {
566+
let x: int;
567+
568+
println!("The value of x is: {}", x);
569+
}
570+
```
571+
572+
And try to build it. You'll get an error:
573+
574+
```{bash}
575+
$ cargo build
576+
Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
577+
src/guessing_game.rs:4:39: 4:40 error: use of possibly uninitialized variable: `x`
578+
src/guessing_game.rs:4 println!("The value of x is: {}", x);
579+
^
580+
note: in expansion of format_args!
581+
<std macros>:2:23: 2:77 note: expansion site
582+
<std macros>:1:1: 3:2 note: in expansion of println!
583+
src/guessing_game.rs:4:5: 4:42 note: expansion site
584+
error: aborting due to previous error
585+
Could not execute process `rustc src/guessing_game.rs --crate-type bin --out-dir /home/you/projects/guessing_game/target -L /home/you/projects/guessing_game/target -L /home/you/projects/guessing_game/target/deps` (status=101)
586+
```
587+
588+
Rust will not let us use a value that has not been initialized. So why let us
589+
declare a binding without initializing it? You'd think our first example would
590+
have errored. Well, Rust is smarter than that. Before we get to that, let's talk
591+
about this stuff we've added to `println!`.
592+
593+
If you include two curly braces (`{}`, some call them moustaches...) in your
594+
string to print, Rust will interpret this as a request to interpolate some sort
595+
of value. **String interpolation** is a computer science term that means "stick
596+
in the middle of a string." We add a comma, and then `x`, to indicate that we
597+
want `x` to be the value we're interpolating. The comma is used to separate
598+
arguments we pass to functions and macros, if you're passing more than one.
599+
600+
When you just use the double curly braces, Rust will attempt to display the
601+
value in a meaningful way by checking out its type. If you want to specify the
602+
format in a more detailed manner, there are a [wide number of options
603+
available](/std/fmt/index.html). Fow now, we'll just stick to the default:
604+
integers aren't very complicated to print.
605+
606+
So, we've cleared up all of the confusion around bindings, with one exception:
607+
why does Rust let us declare a variable binding without an initial value if we
608+
must initialize the binding before we use it? And how does it know that we have
609+
or have not initialized the binding? For that, we need to learn our next
610+
concept: `if`.
611+
612+
## If
613+
614+
## Functions
615+
616+
return
617+
618+
comments
433619

434620
## Compound Data Types
435621

@@ -451,10 +637,35 @@ loop
451637

452638
break/continue
453639

454-
iterators
640+
## Guessing Game: complete
641+
642+
At this point, you have successfully built the Guessing Game! Congratulations!
643+
For reference, [We've placed the sample code on
644+
GitHub](https://github.com/steveklabnik/guessing_game).
645+
646+
You've now learned the basic syntax of Rust. All of this is relatively close to
647+
various other programming languages you have used in the past. These
648+
fundamental syntactical and semantic elements will form the foundation for the
649+
rest of your Rust education.
650+
651+
Now that you're an expert at the basics, it's time to learn about some of
652+
Rust's more unique features.
653+
654+
## iterators
455655

456656
## Lambdas
457657

658+
## Testing
659+
660+
attributes
661+
662+
stability markers
663+
664+
## Crates and Modules
665+
666+
visibility
667+
668+
458669
## Generics
459670

460671
## Traits

0 commit comments

Comments
 (0)