From 8bf85b6a580d399234df0935a7c89850c9c895d4 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" Date: Sun, 3 Jul 2016 14:51:52 -0400 Subject: [PATCH] Backport changes to Variable Bindings in Detail section --- src/SUMMARY.md | 2 +- src/ch03-02-variable-bindings.md | 638 --------------------- src/ch03-03-variable-bindings-in-detail.md | 572 ++++++++++++++++++ 3 files changed, 573 insertions(+), 639 deletions(-) delete mode 100644 src/ch03-02-variable-bindings.md create mode 100644 src/ch03-03-variable-bindings-in-detail.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 1a1e68e..53de811 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -9,7 +9,7 @@ - [Up and Running](ch03-01-up-and-running.md) - [Anatomy of a Rust Program](ch03-02-anatomy-of-a-rust-program.md) - - [Variable Bindings](ch03-02-variable-bindings.md) + - [Variable Bindings in Detail](ch03-03-variable-bindings-in-detail.md) - [Functions](ch03-03-functions.md) - [Scalar Types](ch03-04-scalar-types.md) - [Compound Types](ch03-05-compound-types.md) diff --git a/src/ch03-02-variable-bindings.md b/src/ch03-02-variable-bindings.md deleted file mode 100644 index d9b8d0f..0000000 --- a/src/ch03-02-variable-bindings.md +++ /dev/null @@ -1,638 +0,0 @@ -# Variable Bindings - -The foundation of virtually every program is the ability to store and modify -data. Rust programs are no different. Let’s start with a short example. - -## The basics of bindings - -First, we’ll generate a new project with Cargo. Open a terminal, and navigate -to the directory where you’d like to keep your projects. From there, let’s -generate a new project: - -```bash -$ cargo new --bin bindings -$ cd bindings -``` - -This creates a new project, ‘bindings’, and sets up our `Cargo.toml` and -`src/main.rs` files. As we saw in “Hello, World!”, Cargo will generate these -files and create a little ‘hello world’ program for us: - -```rust -fn main() { - println!("Hello, world!"); -} -``` - -Let’s replace that program with this one: - -```rust -fn main() { - let x = 5; - - println!("The value of x is: {}", x); -} -``` - -And finally, run it: - -```bash -$ cargo run - Compiling bindings v0.1.0 (file:///projects/bindings) - Running `target/debug/bindings` -The value of x is: 5 -``` - -If you see an error instead, double check that you have copied the program -exactly as written. Let’s break this down, line by line. - -```rust,ignore -fn main() { -``` - -The `main()` function is the entry point of every Rust program. We’ll talk more -about functions in the next section, but for now, all we need to know is that -this is where our program begins. The opening curly brace, `{`, indicates the -start of the function’s body. - -```rust,ignore - let x = 5; -``` - -This is our first ‘variable binding’, which we create with a ‘`let` statement’. - -This `let` statement has this form: - -```text -let NAME = EXPRESSION; -``` - -A `let` statement first evaluates the `EXPRESSION`, and then binds the -resulting value to `NAME` so that it can be referred to later in the program. -In our simple example, the expression was already a value, 5, but we could -achieve the same effect with: - -```rust -let x = 2 + 3; -``` - -In general, `let` statements work with patterns; a name is a particularly -humble form of pattern. Patterns are a big part of Rust, we’ll see more complex -and powerful patterns as we go along. - -Before we do that, though, let’s finish investigating this example. Here’s the -next line: - -```rust,ignore - println!("The value of x is: {}", x); -``` - -The `println!` macro prints text to the screen. We can tell that it’s a macro -due to the `!`. We won’t learn how to write macros until much later in the -book, but we’ll use macros provided by the standard library throughout. Every -time you see a `!`, remember that it signifies a macro. Macros can add new -syntax to the language, and the `!` is a reminder that things may look slightly -unusual. - -`println!`, specifically, has one required argument, a ‘format string’, and -zero or more optional arguments. The format string can contain the special text -`{}`. Each instance of `{}` corresponds to an additional argument. Here’s an -example: - -```rust -let x = 2 + 3; -let y = x + 5; -println!("The value of x is {}, and the value of y is {}", x, y); -``` - -You can think of `{}` as little crab pincers, holding the value in place. This -placeholder has a number of more advanced formatting options that we’ll discuss -later. - -```rust,ignore -} -``` - -Finally, a closing curly brace matches up with the opening curly brace that -declared the `main()` function, and declares its end. - -This explains our output: - -```text -The value of x is: 5 -``` - -We assign `5` to a binding, `x`, and then print it to the screen with -`println!`. - -## Multiple binding - -Let’s try a more complex pattern. Change our example program to this: - -```rust -fn main() { - let (x, y) = (5, 6); - - println!("The value of x is: {}", x); - println!("The value of y is: {}", y); -} -``` - -And run it with `cargo run`: - -```text -$ cargo run - Compiling bindings v0.1.0 (file:///projects/bindings) - Running `target/debug/bindings` -The value of x is: 5 -The value of y is: 6 -``` - -We’ve created two bindings with one `let`! Here’s our pattern: - -```text -(x, y) -``` - -And here’s the value: - -```text -(5, 6) -``` - -As you can see, the two line up visually, and so `let` binds `5` to `x` and `6` -to `y`. We could have used two `let` statements as well: - -```rust -fn main() { - let x = 5; - let y = 6; -} -``` - -In simple cases like this, two `let`s may be clearer, but in others, creating -multiple bindings at once is nice. As we become more proficient in Rust, we’ll -figure out which style is better, but it’s mostly a judgement call. - -## Type annotations - -You may have noticed that we didn’t declare the type of `x` or `y` in our -previous examples. Rust is a *statically typed* language, which means that at -compile time, we must know the types of all bindings. But annotating every -single binding with a type can feel like busywork, and make code noisy. To -solve this issue, Rust uses ‘type inference’, meaning that it attempts to infer -the types of your bindings. - -The primary way that the type is inferred is by looking at how it is used. -Let’s look at the example again: - -```rust -fn main() { - let x = 5; -} -``` - -When we bind `x` to `5`, the compiler knows that `x` should be a numeric type. -Without any other information, it defaults to `i32`, a thirty-two bit integer -type. We’ll talk more about Rust’s basic types in section 3.3. - -Here’s what a `let` statement with a ‘type annotation’ looks like: - -```rust -fn main() { - let x: i32 = 5; -} -``` - -We can add a colon, followed by the type name. Here’s the structure of a `let` -statement with a type annotation: - -```text -let PATTERN: TYPE = VALUE; -``` - -Note that the colon and the `TYPE` go _after_ the `PATTERN`, not in the pattern -itself. As an example, here’s our more complex pattern with two bindings: - -```rust -fn main() { - let (x, y): (i32, i32) = (5, 6); -} -``` - -Just like we match up the `VALUE` with the `PATTERN`, we match up the `TYPE` -with the `PATTERN`. - -## Delayed Initialization - -We do not have to provide bindings with an initial value, and can assign it -later. Try this program: - -```rust -fn main() { - let x; - - x = 5; - - println!("The value of x is: {}", x); -} -``` - -And run it with `cargo run`: - -```text -$ cargo run - Compiling bindings v0.1.0 (file:///projects/bindings) - Running `target/debug/bindings` -The value of x is: 5 -``` - -It’s all good. This raises a question, though: what if we try to print out a -binding before we declare a value? Here’s a program that demonstrates this -question: - -```rust,ignore -fn main() { - let x; - - println!("The value of x is: {}", x); - - x = 5; -} -``` - -We can find out the answer with `cargo run`: - -```text - Compiling bindings v0.1.0 (file:///projects/bindings) -src/main.rs:4:39: 4:40 error: use of possibly uninitialized variable: `x` [E0381] -src/main.rs:4 println!(“The value of x is: {}”, x); - ^ -:2:25: 2:56 note: in this expansion of format_args! -:3:1: 3:54 note: in this expansion of print! (defined in ) -src/main.rs:4:5: 4:42 note: in this expansion of println! (defined in ) -src/main.rs:4:39: 4:40 help: run `rustc --explain E0381` to see a detailed explanation -error: aborting due to previous error -Could not compile `bindings`. - -To learn more, run the command again with --verbose. -``` - -An error! The compiler won’t let us write a program like this. This is our -first example of the compiler helping us find an error in our program. -Different programming languages have different ways of approaching this -problem. Some languages always initialize values with some sort of default. -Other languages leave the value uninitialized, and make no promises about what -happens if you try to use something before initialization. Rust chooses -something else: error and force the programmer to explain what they want. We -must do some sort of initialization before we can use `x`. - -### Extended error explanations - -There’s one more interesting part of this error message: - -```text -src/main.rs:4:39: 4:40 help: run `rustc --explain E0381` to see a detailed explanation -``` - -We can see an extended explanation by passing the `--explain` flag to `rustc`. -Not every error has a longer explanation, but many of them do. These extended -explanations try to show off common ways that the error occurs, and common -solutions to the issue. Here’s `E0381`: - -```bash -$ rustc --explain E0381 -It is not allowed to use or capture an uninitialized variable. For example: - -fn main() { - let x: i32; - let y = x; // error, use of possibly uninitialized variable - -To fix this, ensure that any declared variables are initialized before being -used. -``` - -These explanations can really help if you’re stuck on an error. The compiler is -your friend, and is here to help. - -## Mutable bindings - -What about changing the value of a binding? Here’s another sample program that -asks this question: - -```rust,ignore -fn main() { - let x = 5; - - x = 6; - - println!("The value of x is: {}", x); -} -``` - -`cargo run` has the answer for us: - -```bash -$ cargo run - Compiling bindings v0.1.0 (file:///projects/bindings) -src/main.rs:4:5: 4:10 error: re-assignment of immutable variable `x` [E0384] -src/main.rs:4 x = 6; - ^~~~~ -src/main.rs:4:5: 4:10 help: run `rustc --explain E0384` to see a detailed explanation -src/main.rs:2:9: 2:10 note: prior assignment occurs here -src/main.rs:2 let x = 5; - ^ -``` - -The error mentions `re-assigment of immutable variable`. That’s right: bindings -are immutable. But they’re only immutable by default. In a pattern, when we’re -creating a new name, we can add `mut` in front to make the binding a mutable -one. Here’s an example: - -```rust -fn main() { - let mut x = 5; - - println!("The value of x is: {}", x); - - x = 6; - - println!("The value of x is: {}", x); -} -``` - -Running this, we get: - -```bash -$ cargo run - Compiling bindings v0.1.0 (file:///projects/bindings) - Running `target/debug/bindings` -The value of x is: 5 -The value of x is: 6 -``` - -We can now change the value that `x` binds to. Note that the syntax is not `let -mut` exactly; it’s using `mut` in a pattern. This becomes more obvious with our -`()` pattern: - - -```rust,ignore -fn main() { - let (mut x, y) = (5, 6); - - x = 7; - y = 8; -} -``` - -The compiler will complain about this program: - -```bash -$ cargo build - Compiling bindings v0.1.0 (file:///projects/bindings) -src/main.rs:5:5: 5:10 error: re-assignment of immutable variable `y` [E0384] -src/main.rs:5 y = 8; - ^~~~~ -src/main.rs:5:5: 5:10 help: run `rustc --explain E0384` to see a detailed explanation -src/main.rs:2:17: 2:18 note: prior assignment occurs here -src/main.rs:2 let (mut x, y) = (5, 6); - ^ -``` - -It’s fine with re-assigning `x`, but not `y`. The `mut` only applies to the -name that follows it, not the whole pattern. - -### Reassignment, not mutation - -There is one subtlety we haven’t covered yet: `mut` allows you to mutate _the -binding_, but not _what the binding binds to_. In other words: - -```rust -fn main() { - let mut x = 5; - - x = 6; -} -``` - -This is not changing the value that `x` is bound to, but creating a new value, -`6`, and changing the binding to bind to it instead. It’s a subtle but -important difference. Well, for now, it does not make a lot of difference, but -when our programs get more complex, it will. Specifically, passing arguments to -functions will illustrate the difference. We’ll talk about that in the next -section, when we discuss functions. - -## Scope - -Variable bindings have a ‘scope’ in which they’re valid. That scope begins from -the point at which the binding is declared, and ends at the end of the next -block of code. We can only access bindings which are ‘in scope’. We cannot -access them ‘before they come into scope’ or ‘after they go out of scope’. -Here’s an example: - -```rust -fn main() { - println!("x is not yet in scope"); - - let x = 5; - println!("x is now in scope"); - - println!("In real code, we’d now do a bunch of work."); - - println!("x will go out of scope now! The next curly brace is ending the main function."); -} -``` - -We can create arbitrary scopes through the use of `{` and `}`: - -```rust -fn main() { - println!("x is not yet in scope"); - - let x = 5; - println!("x is now in scope"); - - println!("Let’s start a new scope!"); - - { - let y = 5; - println!("y is now in scope"); - println!("x is also still in scope"); - - println!("y will go out of scope now!"); - println!("The next curly brace is ending the scope we started."); - } - - println!("x is still in scope, but y is now out of scope and is not usable"); - - println!("x will go out of scope now! The next curly brace is ending the main function."); -} -``` - -What bindings are in and out of scope will become much more important later, -once we learn about ‘references’ and ‘traits’. - -## Shadowing - -A final thing about bindings: they can ‘shadow’ previous bindings with the same -name. Here’s a sample program: - -```rust -fn main() { - let x = 5; - let x = 6; - - println!("The value of x is: {}", x); -} -``` - -Running it, we can see the shadowing in action: - -```text -src/main.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variables)] on by default -src/main.rs:2 let x = 5; - ^ - Running `target/debug/bindings` -The value of x is: 6 -``` - -There are two interesting things in this output. First, Rust will compile and -run this program, no problem. And as we can see, the value of `x` is `6`. But -we didn’t declare `x` as mutable. Instead, we declared a _new_ binding that is -_also_ named `x`, and gave it a new value. The older value that we bound `x` to -is inaccessible as soon as the new `x` is declared. This can be useful if you’d -like to perform a few transformations on a value, and leave it immutable. For -example: - -```rust -fn main() { - let x = 5; - let x = x + 1; - let x = x * 2; - - println!("The value of x is: {}", x); -} -``` - -This will print: - -```bash - Compiling bindings v0.1.0 (file:///projects/bindings) - Running `target/debug/bindings` -The value of x is: 12 -``` - -This lets us modify `x`, but not deal with mutation. This is nice because we -know that the compiler will let us know if we try to modify it later. Let’s -assume that after we calculate `12`, we don’t want to modify `x` again. If we -had written this program in a mutable style, like this: - -```rust -fn main() { - let mut x = 5; - x = x + 1; - x = x * 2; - - println!("The value of x is: {}", x); - - x = 15; - - println!("The value of x is: {}", x); -} -``` - -Rust is happy to let us mutate it again, to `15`. A similar program in our -immutable style will let us know about that accidental mutation, however: - -```rust,ignore -fn main() { - let x = 5; - let x = x + 1; - let x = x * 2; - - println!("The value of x is: {}", x); - - x = 15; - - println!("The value of x is: {}", x); -} -``` - -If we try to compile, we get an error: - -```bash -$ cargo build - Compiling bindings v0.1.0 (file:///projects/bindings) -src/main.rs:8:5: 8:11 error: re-assignment of immutable variable `x` [E0384] -src/main.rs:8 x = 15; - ^~~~~~ -src/main.rs:8:5: 8:11 help: run `rustc --explain E0384` to see a detailed explanation -src/main.rs:4:9: 4:10 note: prior assignment occurs here -src/main.rs:4 let x = x * 2; - ^ -error: aborting due to previous error -Could not compile `bindings`. -``` - -Exactly what we wanted. - -Shadowing can take some time to get used to, but it’s very powerful, and works -well with immutability. - -There was one more thing we should talk about in the output from compiling our -initial program. It’s this part: - -```text -src/main.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variables)] on by default -``` - -Here’s the two lines of relevant code: - -```rust -let x = 5; -let x = 6; -``` - -Rust knows that we shadowed `x`, but we never ended up using the initial value. -This isn’t _wrong_, exactly, it just may not have been what we wanted. In this -case, the compiler issues a ‘warning’, but still compiles our program. The -`#[warn(unused_variables)]` syntax is called an ‘attribute’, which we’ll -discuss in a later section. More specifically, a warning like this is called a -‘lint’, which is an old term for the bits of sheep’s wool that you wouldn’t -want to put in cloth. Similarly, this lint is telling us that we may have an -extra bit of code we don’t need. Our program would work just fine without it. -It’s worth listening to these warnings, and fixing the problems they point out. -They can be signs of a larger problem. In this case, we may not have realized -that we were shadowing `x`. - -### Shadowing and scopes - -Like any binding, a binding that shadows another binding will go away at the -end of a scope. Here’s an example program: - -```rust -fn main() { - let x = 5; - - println!("Before shadowing, x is: {}", x); - - { - let x = 6; - - println!("Now that x is shadowed, x is: {}", x); - } - - println!("After shadowing, x is: {}", x); -} -``` - -If we run this example, we can see the shadow appear and disappear: - -```bash -$ cargo run - Compiling bindings v0.1.0 (file:///projects/bindings) - Running `target/debug/bindings` -Before shadowing, x is: 5 -Now that x is shadowed, x is: 6 -After shadowing, x is: 5 -``` diff --git a/src/ch03-03-variable-bindings-in-detail.md b/src/ch03-03-variable-bindings-in-detail.md new file mode 100644 index 0000000..efb6461 --- /dev/null +++ b/src/ch03-03-variable-bindings-in-detail.md @@ -0,0 +1,572 @@ +## Variable Bindings in Detail + +So far, we’ve created the simplest kind of variable binding, but the `let` +statement has some more tricks up its sleeve. Now we'll look at doing more +complex things: creating multiple bindings at once, adding type annotations, +creating mutating bindings, understanding shadowing, and more. + +### Creating Multiple Bindings + +The previous example program just bound one variable, but it's also possible to +create multiple variable bindings in one go. Let’s try a more complex example, +creating two variable bindings at once. Change your example program to this: + + + +```rust +fn main() { + let (x, y) = (5, 6); + + println!("The value of x is: {}", x); + println!("The value of y is: {}", y); +} +``` + +And enter `cargo run` to run it: + +```bash +$ cargo run + Compiling bindings v0.1.0 (file:///projects/bindings) + Running `target/debug/bindings` +The value of x is: 5 +The value of y is: 6 +``` + +We’ve created two bindings with one `let` statement! The `let` statement binds +the values in `(5, 6)` to the corresponding patterns of `(x, y)`. The first +value `5` binds to the first part of the pattern, `x`, and the second value `6` +binds to `y`. We could alternatively have used two `let` statements to the same +effect, as follows: + +```rust +fn main() { + let x = 5; + let y = 6; +} +``` + +In simple cases like this, where we are only binding two variables, two `let` +statements may be clearer in the code, but when you're creating many multiple +bindings, it's useful to be able to do so all at once. Deciding which technique +to use is mostly a judgement call, and as you become more proficient in Rust, +you’ll be able to figure out which style is better in each case. + +### Delayed Initialization + +The examples so far have all provided bindings with an initial value, but that +isn't always necessary. Rather, we can assign a value for the binding later, +after the `let` statement. To try this out, write the following program: + +```rust +fn main() { + let x; + + x = 5; + + println!("The value of x is: {}", x); +} +``` + +And enter `cargo run` to run it: + +```bash +$ cargo run + Compiling bindings v0.1.0 (file:///projects/bindings) + Running `target/debug/bindings` +The value of x is: 5 +``` + +As you can see, this works just like the previous program, in which we assigned +an initial value. + +This raises an interesting question: what happens if we try to print out a +binding before we declare a value? Let's find out. Modify your code to look +like the following: + +```rust,ignore +fn main() { + let x; + + println!("The value of x is: {}", x); + + x = 5; +} +``` + +When you enter `cargo run` to run this code, you should see output like this +after the command: + +```bash + Compiling bindings v0.1.0 (file:///projects/bindings) +src/main.rs:4:39: 4:40 error: use of possibly uninitialized variable: `x` [E0381] +src/main.rs:4 println!("The value of x is: {}", x); + ^ +:2:25: 2:56 note: in this expansion of format_args! +:3:1: 3:54 note: in this expansion of print! (defined in ) +src/main.rs:4:5: 4:42 note: in this expansion of println! (defined in ) +src/main.rs:4:39: 4:40 help: run `rustc --explain E0381` to see a detailed explanation +error: aborting due to previous error +Could not compile `bindings`. + +To learn more, run the command again with --verbose. +``` + +There's been an error! The compiler won’t let us write a program like this, and +instead it requests that you assign a value to the variable `x`. This is our +first example of the compiler helping us find an error in our program. +Different programming languages have different ways of approaching this +problem. Some languages will always initialize values with some sort of +default. Other languages leave the value uninitialized, and make no promises +about what happens if you try to use something before initialization. Rust +responds with an error to prod the programmer to declare the value they want. +We must initialize any variable before we can use it. + +PROD: START BOX +######Extended Error Explanations + +Now that you've seen an example of a Rust error, I want to point out one +particularly useful aspect of errors. Rust encourages you to seek further +information on the kind of error you've received with output like this: + +```bash +src/main.rs:4:39: 4:40 help: run `rustc --explain E0381` to see a detailed explanation +``` + +This tells us that if we pass the `--explain` flag to `rustc` with the provided +error code, we can see an extended explanation, which will try to explain +common causes of and solutions to that kind of error. Not every error has a +longer explanation, but many do. Here’s the explanation for the `E0381` error +we received previously: + +```bash +$ rustc --explain E0381 +It is not allowed to use or capture an uninitialized variable. For example: + +fn main() { + let x: i32; + + let y = x; // error, use of possibly uninitialized variable + +To fix this, ensure that any declared variables are initialized before being +used. +``` + +These explanations can really help if you’re stuck on an error, so don't +hesitate to look up the error code. The compiler is your friend, and it's there +to help. + +PROD: END BOX + +### Mutable bindings + +By default, variable bindings are *immutable*, meaning that once a value is +bound, you can't change that value. Try writing the following sample program to +illustrate this: + +```rust,ignore +fn main() { + let x = 5; + + x = 6; + + println!("The value of x is: {}", x); +} +``` + +Save and run the program, and you should receive another error message, as in +this output: + +```bash +$ cargo run + Compiling bindings v0.1.0 (file:///projects/bindings) +src/main.rs:4:5: 4:10 error: re-assignment of immutable variable `x` [E0384] +src/main.rs:4 x = 6; + ^~~~~ +src/main.rs:4:5: 4:10 help: run `rustc --explain E0384` to see a detailed explanation +src/main.rs:2:9: 2:10 note: prior assignment occurs here +src/main.rs:2 let x = 5; + ^ +``` + +The error includes the message `re-assigment of immutable variable` because the +program tried to assign a second value to the `x` variable. But bindings are +immutable only by default; you can make them mutable by adding `mut` in front +of the variable name. For example, change the program you just wrote to the +following: + +```rust +fn main() { + let mut x = 5; + + println!("The value of x is: {}", x); + + x = 6; + + println!("The value of x is: {}", x); +} +``` + +Running this, we get: + +```bash +$ cargo run + Compiling bindings v0.1.0 (file:///projects/bindings) + Running `target/debug/bindings` +The value of x is: 5 +The value of x is: 6 +``` + +Using `mut`, we change the value that `x` binds to from `5` to `6`. Note, +however, that `mut` is part of the pattern in the `let` statement. This becomes +more obvious if we try to add mutability to a pattern that binds multiple +variables in the same way as we did for a single variable, like this: + + +```rust,ignore +fn main() { + let (mut x, y) = (5, 6); + + x = 7; + y = 8; +} +``` + +If you run this code, the compiler will output an error: + +```bash +$ cargo run + Compiling bindings v0.1.0 (file:///projects/bindings) +src/main.rs:5:5: 5:10 error: re-assignment of immutable variable `y` [E0384] +src/main.rs:5 y = 8; + ^~~~~ +src/main.rs:5:5: 5:10 help: run `rustc --explain E0384` to see a detailed explanation +src/main.rs:2:17: 2:18 note: prior assignment occurs here +src/main.rs:2 let (mut x, y) = (5, 6); + ^ +``` + +The way `mut` is used here, the compiler is fine with reassigning the `x` +variable, but not the `y` variable. That's because `mut` only applies to the +name that directly follows it, not the whole pattern. For the compiler to allow +you to reassign the `y` variable, you'd need to write the pattern as `(mut x, +mut y)` instead. + + + +One thing to know about mutating bindings: `mut` allows you to mutate _the +binding_, but not _what the name binds to_. In other words, the value is not +what changes, but rather the path between the value and the name. For example: + +```rust +fn main() { + let mut x = 5; + + x = 6; +} +``` + +This does not change the value that `x` is bound to, but creates a new value +(`6`) and changes the binding so that it binds the name `x` to this new value +instead. This subtle but important difference will become more important as +your Rust programs get more complex. + + + +### Variable Binding Scope + +Another important thing to know about variable bindings is that they are only +valid as long as they are *in scope*. That scope begins at the point where the +binding is declared, and ends with the curly brace that closes the block of +code containing that binding. We cannot access bindings "before they come into +scope" or "after they go out of scope." Here’s an example to illustrate this: + + + +```rust +fn main() { + println!("x is not yet in scope"); + + let x = 5; + + println!("x is now in scope"); + + println!("In real code, we’d now do a bunch of work."); + + println!("x will go out of scope now! The next curly brace is ending the main function."); +} +``` + +The variable binding for `x` goes out of scope with the last curly brace in the +`main()` function. + +This example only has one scope, though. In Rust, it's possible to create +arbitrary scopes within a scope by placing code within another pair of curly +braces (we'll look at this more in the next chapter). For example: + +```rust +fn main() { + + println!("x is not yet in scope"); + + let x = 5; + + println!("x is now in scope"); + + println!("Let’s start a new scope!"); + + { + let y = 5; + + println!("y is now in scope"); + println!("x is also still in scope"); + + println!("y will go out of scope now!"); + println!("The next curly brace is ending the scope we started."); + } + + println!("x is still in scope, but y is now out of scope and is not usable"); + + println!("x will go out of scope now! The next curly brace is ending the main function."); +} +``` + +The `y` variable is only in scope in the section of the code that's between the +nested pair of curly braces, whereas `x` is in scope from the `let` statement +that binds it until the final curly brace. The scope of bindings will become +much more important later as you learn about references in Chapter XX. + +### Shadowing Earlier Bindings + + + +One final thing about bindings: they can *shadow* previous bindings with the +same name. Shadowing is what happens when you declare two bindings with the +same name. We say that the first binding is ‘shadowed’ by the second, which +means that the second binding's value is what you will see when you use the +variable after the second binding. This can be useful if you’d like to perform +a few transformations on a value, but still leave the binding immutable. For +example: + +```rust +fn main() { + let x = 5; + + let x = x + 1; + + let x = x * 2; + + println!("The value of x is: {}", x); +} +``` + +This program first binds `x` to a value of `5`. Then, it shadows `x`, taking +the original value and adding `1` so that the value of `x` is then `6`. The +third `let` statement shadows `x` again, taking the previous value and +multiplying it by `2` to give `x` a final value of `12`. If you run this, it +will output: + +```bash +$ cargo run + Compiling bindings v0.1.0 (file:///projects/bindings) + Running `target/debug/bindings` +The value of x is: 12 +``` + +Shadowing is useful because it lets us modify `x` without having to make the +variable mutable. This means the compiler will still warn us if we accidentally +try to mutate `x` directly later. For example, say after calculating `12` we +don’t want `x` to be modified again; if we write the program in a mutable +style, like this: + +```rust +fn main() { + let mut x = 5; + + x = x + 1; + x = x * 2; + + println!("The value of x is: {}", x); + + x = 15; + + println!("The value of x is: {}", x); +} +``` + +Rust is happy to let us mutate `x` again, to `15`. A similar program using the +default immutable style, however, will let us know about that accidental +mutation. Here's an example: + +```rust,ignore +fn main() { + let x = 5; + let x = x + 1; + let x = x * 2; + + println!("The value of x is: {}", x); + + x = 15; + + println!("The value of x is: {}", x); +} +``` + +If we try to compile this, we get an error: + +```bash +$ cargo run + Compiling bindings v0.1.0 (file:///projects/bindings) +src/main.rs:8:5: 8:11 error: re-assignment of immutable variable `x` [E0384] +src/main.rs:8 x = 15; + ^~~~~~ +src/main.rs:8:5: 8:11 help: run `rustc --explain E0384` to see a detailed explanation +src/main.rs:4:9: 4:10 note: prior assignment occurs here +src/main.rs:4 let x = x * 2; + ^ +error: aborting due to previous error +Could not compile `bindings`. +``` + +Since we don't want the binding to be mutable, this exactly what should happen. + +#### Shadowing Over Bindings + +You can also shadow bindings over one another, without re-using the initial +binding in the value. Here's how that looks: + +```rust +fn main() { + let x = 5; + let x = 6; + + println!("The value of x is: {}", x); +} +``` + +Running this sample program, we can see the shadowing in action: + +```bash +$ cargo run + Compiling bindings v0.1.0 (file:///projects/bindings) +src/main.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variables)] on by default +src/main.rs:2 let x = 5; + ^ + Running `target/debug/bindings` +The value of x is: 6 +``` + +Rust gives the value of `x` as `6`, which is the value from the *second* `let` +statement. There are a few interesting things in this output. First, that Rust +will compile and run the program without issue. This is because we haven't +mutated the value; instead, we declared a _new_ binding that is _also_ named +`x`, and gave it a new value. + +The other interesting thing in this output is this error line: + +```bash +src/main.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variables)] on by default +``` + +Rust is pointing out that we shadowed `x`, but never used the initial value. +Doing so isn’t _wrong_, but Rust is checking whether this is intentional and +not just a mistake. In this case, the compiler issues a warning, but still +compiles our program. A warning like this is called a *lint*, which is an old +term for the bits of fluff and fibers in sheep’s wool that you wouldn't want to +put in cloth. + +Similarly, this lint is telling us that we may have an extra bit of code (the +statement `let x = 5`) that we don’t need. Even though our program works just +fine, listening to these warnings and fixing the problems they point out is +worthwhile, as they can be signs of a larger problem. In this case, we may not +have realized that we were shadowing `x`, when we meant to, say, define a new +variable with a different name. + +Shadowing can take some time to get used to, but it’s very powerful and works +well with immutability. + +#### Shadowing and Scopes + +Like any binding, a binding that shadows another binding becomes invalid at the +end of a scope. Here’s an example program to illustrate this: + +```rust +fn main() { + let x = 5; + + println!("Before shadowing, x is: {}", x); + + { + let x = 6; + + println!("Now that x is shadowed, x is: {}", x); + } + + println!("After shadowing, x is: {}", x); +} +``` + +This code first creates the `x` variable and prints `x` to the terminal. Then, +inside a new scope, it creates a new binding for `x` with a new value, and +prints that value. When the arbitrary scope ends, `x` is printed once more. If +we run this example, we can see the shadow appear and disappear in the output: + +```bash +$ cargo run + Compiling bindings v0.1.0 (file:///projects/bindings) + Running `target/debug/bindings` +Before shadowing, x is: 5 +Now that x is shadowed, x is: 6 +After shadowing, x is: 5 +``` + +In this case, the binding value reverts to the original value once the shadow +binding goes out of scope.