From fd2dc5e2e02d86a23c85c9be7db1779b0449ff0c Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Fri, 8 Jan 2016 12:09:26 -0500 Subject: [PATCH] Add stuff about nostarch --- README.md | 7 + nostarch/chapter3.md | 1994 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2001 insertions(+) create mode 100644 nostarch/chapter3.md diff --git a/README.md b/README.md index 597c050..8659101 100644 --- a/README.md +++ b/README.md @@ -76,3 +76,10 @@ Finally, there’s the `S-` labels, which are for various ‘status’es: * `S-done`: imported into No Starch’s system. There may still be changes based on their feedback, even after a section is marked `S-done`. +## No Starch + +As the book will be published by No Starch, we first iterate here, then ship the +text off to No Starch. Then they do editing, and we fold it back in. + +As such, there’s a directory, `nostarch`, which corresponds to the `S-done`, +and its current status in No Starch’s system. diff --git a/nostarch/chapter3.md b/nostarch/chapter3.md new file mode 100644 index 0000000..4f15f17 --- /dev/null +++ b/nostarch/chapter3.md @@ -0,0 +1,1994 @@ +# Up and Running + +We’ll start our journey with Rust by talking about the absolute basics — +concepts that appear in almost every programming language. Many programming +languages have lots in common at their core. None of the concepts presented are +unique to Rust, but we’ll cover Rust’s particular syntax and conventions around +these common concepts. + +If you want to skip this section, you can, but you may end up coming back later +to find out small details. These foundations will be in every single useful +Rust program, and learning them gives us a strong core to start from. +# 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: + +``` +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 +``` +# Functions + +Functions are pervasive in Rust code. We’ve already seen the most important +function, `main()`, in previous sections of the book: + +```rust +fn main() { + println!("Hello, world!"); +} +``` + +We can declare new functions with the `fn` keyword: + +```rust +fn another_function() { + println!("Another function."); +} +``` + +Rust code uses `snake_case` as a style for function names: all lower case, with +underscores separating words. (It also uses them for variable names, too.) We +can can call any function we’ve defined by using its name and some parentheses: + +```rust +fn main() { + println!("Hello, world!"); + + another_function(); +} + +fn another_function() { + println!("Another function."); +} +``` + +Let’s start a new project to explore functions. Open a terminal, and navigate +to the directory where you’d like to keep your projects. From there, use Cargo +to generate a new project: + +```bash +$ cargo new --bin functions +$ cd functions +``` + +Place the new example in `src/main.rs`, and run it: + +```bash +$ cargo run + Compiling functions v0.1.0 (file:///projects/functions) + Running `target/debug/functions` +Hello, world! +Another function. +``` + +As we can see, the lines execute in order: first, we print out our “Hello, +world!” message, and then `another_function()` is called. It then prints its +message as well. + +## Function Arguments + +Functions can also take arguments: + +```rust +fn main() { + another_function(5); +} + +fn another_function(x: i32) { + println!("The value of x is: {}", x); +} +``` + +Let’s try running it: + +```bash +$ cargo run + Compiling functions v0.1.0 (file:///projects/functions) + Running `target/debug/functions` +The value of x is: 5 +``` + +Let’s take a closer look at `another_function()`’s signature: + +```rust,ignore +fn another_function(x: i32) { +``` + +Declaring a function which takes a single argument looks like this: + +```text +fn NAME(PATTERN: TYPE) { +``` + +That’s right, patterns appear again. Consider how the parameter declaration +here looks like the `let` bindings we used earlier: + +```rust,ignore +let x: i32; +fn another_function(x: i32) { +``` + +There’s only one difference here: in function signatures, we _must_ declare the +type. This is a deliberate decision; we find that requiring type annotations in +functions means that you almost never need them anywhere else. + +You can separate multiple arguments with a comma: + +```text +fn NAME(PATTERN, PATTERN, PATTERN, PATTERN...) { +``` + +Here’s a full example: + +```rust +fn main() { + another_function(5, 6); +} + +fn another_function(x: i32, y: i32) { + println!("The value of x is: {}", x); + println!("The value of y is: {}", y); +} +``` + +Let’s try it: + +```bash +$ cargo run + Compiling functions v0.1.0 (file:///projects/functions) + Running `target/debug/functions` +The value of x is: 5 +The value of y is: 6 +``` + +We could also create bindings, and pass them in as arguments: + +```rust +fn main() { + let a = 5; + let b = 6; + + another_function(a, b); +} + +fn another_function(x: i32, y: i32) { + println!("The value of x is: {}", x); + println!("The value of y is: {}", y); +} +``` + +This has the same effect: + +```bash +$ cargo run + Compiling functions v0.1.0 (file:///projects/functions) + Running `target/debug/functions` +The value of x is: 5 +The value of y is: 6 +``` + +Note that our bindings are called `a` and `b`, yet inside of the function, we +refer to them by the names in the signature, `x` and `y`. Inside a function, +only its parameters are in scope, so we need to use those names. Bindings +passed as parameters don’t need to have the same name as the arguments. + +## Return values + +Functions can also return values back to the function that called them: + +```TEXT +fn NAME(PATTERN, PATTERN, PATTERN, PATTERN...) -> TYPE { +``` + +We don’t name return values, but we do declare their type, after an arrow: +`->`. Here’s a sample program: + +```rust +fn main() { + let x = five(); + + println!("The value of x is: {}", x); +} + +fn five() -> i32 { + 5 +} +``` + +Let’s try running it: + +```bash +$ cargo run + Compiling functions v0.1.0 (file:///projects/functions) + Running `target/debug/functions` +The value of x is: 5 +``` + +Let’s examine this in more detail. There are two important bits. First, we can +use the return value of a function to initialize a binding: + +```rust,ignore +let x = five(); +``` + +Because `five()` returns a `5`, this is the same as: + +```rust +let x = 5; +``` + +The second interesting bit is `five()` itself: + +```rust +fn five() -> i32 { + 5 +} +``` + +We have no arguments, and our return type, `i32`. However, the body of this +function is a lonely `5`. There’s a detail here that you may or may not have +noticed: we’ve ended almost every line in our programs with a semicolon. +There’s no semicolon here, though. Why not? + +The answer to this question is: + +> The return value of a function is the value of its final expression. + +We haven’t talked about expressions yet, so this definition doesn’t help a lot. +Let’s go over that now. + +## Statements and Expressions + +Expressions are bits of code that evaluate to a value. Consider some math +operations, like this: + +```rust,ignore +5 + 6 +``` + +We can evaluate this expression, and come up with a value: `11`. In Rust, most +bits of code are expressions. For example, calling a function is an expression: + +```rust,ignore +foo(5) +``` + +The value is equal to whatever the return value of `foo()` is. + +So why does this matter? Well, not everything is an expression. Some things are +‘statements’. Expressions _compute_ something, but statements _bind_ or _do_ +something. It’s a subtle difference. We’ve already seen two kinds of +statements: `let` statements, and `fn` declarations. + +Because `let` is a statement, not an expression, you can’t assign it to another +binding. Here’s an example that doesn’t work: + +```rust,ignore +fn main() { + let x = (let y = 6); +} +``` + +If we try to run this program, we’ll get an error: + +```bash +$ cargo run + Compiling functions v0.1.0 (file:///projects/functions) +src/main.rs:2:14: 2:17 error: expected identifier, found keyword `let` +src/main.rs:2 let x = (let y = 6); + ^~~ +src/main.rs:2:18: 2:19 error: expected one of `!`, `)`, `,`, `.`, `::`, `{`, or an operator, found `y` +src/main.rs:2 let x = (let y = 6); + ^ +Could not compile `functions`. +``` + +We also cannot somehow assign a `fn` declaration to a binding, either. + +So what’s this have to do with return values? Well, `{}`, a ‘block’ that we +used earlier to create new scopes, _is_ an expression. Let’s take a closer look +at `{}`. It looks like this: + +```text +{ + STATEMENT* + EXPRESSION +} +``` + +The `*` there means ‘zero or more’, so we can have any number of statements +followed by an expression. Since blocks are expressions themselves, we can nest +blocks inside of blocks. And since they return a value, we can use them in +`let` statements: + +```rust +fn main() { + let x = 5; + + let y = { + let z = 1; + + x + z + 5 + }; + + println!("The value of y is: {}", y); +} +``` + +Let’s try running this program: + +```bash + Compiling functions v0.1.0 (file:///projects/functions) + Running `target/debug/functions` +The value of y is: 11 +``` + +We’re now using a block to give us a value for `y`: + +```rust,ignore +let y = { + +}; +``` + +Since the block can contain statements, we create a new variable binding, `z`, +and give it a value. We then do some math for the final expression of the +block: + +```rust,ignore +{ + let z = 1; + + x + z + 5 +} +``` + +`5 + 1 + 5` is `11`, and so the value of the entire block is `11`. This gets +substituted into our `let` statement for `y`: + +```rust,ignore +let y = 11; +``` + +Hence our output saying `y` is `11`. + +Where else do we use blocks? As the body of functions! They’re very similar: + +```rust +fn main() { + let x = 5; + + let y = { + x + 1 + }; + + println!("The value of y is: {}", y); + + let y = plus_one(x); + + println!("The value of y is: {}", y); +} + +fn plus_one(x: i32) -> i32 { + x + 1 +} +``` + +Running this gives: + +```bash +$ cargo run + Compiling functions v0.1.0 (file:///projects/functions) + Running `target/debug/functions` +The value of y is: 6 +The value of y is: 6 +``` + +In both cases, we use a block to produce a value. In the first case, it’s +assigning with `let`: + +```rust,ignore +let y = { +``` + +In the second, it’s the return value of the function: + +```rust,ignore +fn plus_one(x: i32) -> i32 { +``` + +### Expression statements + +There’s one more detail about expressions and statements: a semicolon takes any +expression, and turns it into a statement. Let’s accidentally cause an error +with `plus_one()`: + +```rust,ignore +fn main() { + let x = plus_one(5); + + println!("The value of x is: {}", x); +} + +fn plus_one(x: i32) -> i32 { + x + 1; +} +``` + +Instead of an expression, `x + 1`, we’ve now turned it into a statement, +`x + 1;`. + +Running this gives an error: + +```bash +$ cargo run + Compiling functions v0.1.0 (file:///projects/functions) +src/main.rs:7:1: 9:2 error: not all control paths return a value [E0269] +src/main.rs:7 fn plus_one(x: i32) -> i32 { +src/main.rs:8 x + 1; +src/main.rs:9 } +src/main.rs:7:1: 9:2 help: run `rustc --explain E0269` to see a detailed explanation +src/main.rs:8:10: 8:11 help: consider removing this semicolon: +src/main.rs:8 x + 1; + ^ +error: aborting due to previous error +Could not compile `functions`. +``` + +Rust has our back here: it even suggests removing the semicolon, which fixes +the error. But the main error message is the core of the issue: statements +don’t evaluate to a value, yet we want to return an `i32`. + +In practice, Rust programmers don’t often think about these rules at this +level. Usually, you have a semicolon at the end of most lines, and maybe not at +the end of blocks. + +## Multiple return values + +Functions cannot directly return multiple values. There’s a trick, however. +Remember the `()`s we used when showing off complex bindings? + +```rust +fn main() { + let (x, y) = (5, 6); +} +``` + +They form something called a ‘tuple’, one of Rust’s basic types. A tuple is an +anonymous collection of elements. But since a tuple is a singular thing, we can +use it as a way to return multiple values from functions: + +```rust +fn main() { + let (x, y) = two_numbers(); + + println!("The value of x is: {}", x); + println!("The value of y is: {}", y); +} + +fn two_numbers() -> (i32, i32) { + (5, 6) +} +``` + +Running this will show us the values: + +```bash +$ cargo run + Compiling functions v0.1.0 (file:///projects/functions) + Running `target/debug/functions` +The value of x is: 5 +The value of y is: 6 +``` + +There are two interesting changes here: assigning the return value of +`two_numbers()` to `x` and `y`, and the declaration of `two_numbers()` itself. + +Let’s look at the declaration first: + +```rust +fn two_numbers() -> (i32, i32) { + (5, 6) +} +``` + +The `(i32, i32)` should look familiar. We saw it in `let` bindings earlier: + +```rust +let (x, y): (i32, i32) = (5, 6); +``` + +The `(i32, i32)` syntax says “a tuple with two `i32`s in it.” The `(5, 6)` +syntax creates a new one, with `5` and `6`. + +This tuple is then returned, and assigned to `x` and `y`: + +```rust,ignore +let (x, y) = two_numbers(); +``` + +See how all these bits fit together? + +We call this behavior of `let` ‘destructuring’, because it takes the structure +of the expression that comes after the `=` and takes it apart. +# Scalar Types + +We’ve seen that every value in Rust has a type of some kind. There are a number +of types which are built into the language itself. First, we’ll take a look at +‘scalar’ types, that is, types which represent a single value. + +Remember, you can rely on type inference to figure out the type of a binding, +or you can annotate it explicitly: + +```rust +fn main() { + let x: i32 = 5; +} +``` + +## Integers + +You’ve already seen one primitive type: `i32`. There are a number of built-in +number types in Rust. + +Here’s a chart of Rust’s integer types: + +| | signed | unsigned | +|--------|--------|----------| +| 8-bit | i8 | u8 | +| 16-bit | i16 | u16 | +| 32-bit | i32 | u32 | +| 64-bit | i64 | u64 | +| arch | isize | usize | + +We have both signed and unsigned variants of numbers, and each variant has an +explicit size. Unsigned numbers are never negative, and signed numbers can be +positive or negative. (Think ‘plus sign’ or ‘minus sign’: that’s a signed +number.) Signed numbers are stored using ‘two’s complement’ representation. + +Finally, `isize` and `usize` are different sizes based on the kind of computer +your program is running on. If you are on a 64-bit architecture, they are 64 +bits, and if you’re on a 32-bit one, they’re 32 bits. + +So how do you choose from all these options? Well, if you really don’t know, +the defaults are a good choice: integer types default to `i32`. The primary use +case for `isize`/`usize` is when indexing some sort of collection. We’ll talk +more about our first collection, arrays, in just a moment. + +## Floating-point numbers + +Rust also has two primitive floating-point numbers: `f32` and `f64`. They are +32 bits and 64 bits in size, respectively. The default is `f64`. + +```rust +fn main() { + let x = 2.0; // f64 + + let y: f32 = 3.0; // f32 +} +``` + +Floating-point numbers are represented according to the IEEE-754 standard. +`f32` is a single-precision float, `f64` is double-precision. + +## Numeric operations + +Rust supports the usual operations you’d expect on all of these number types: + +```rust +fn main() { + // addition + let sum = 5 + 10; + + // subtraction + let difference = 95.5 - 4.3; + + // multiplication + let product = 4 * 30; + + // division + let quotient = 56.7 / 32.2; + + // modulus + let remainder = 43 % 5; +} +``` + +## Booleans + +Somewhat fundamental to all computing, Rust has a boolean type, `bool`, with +two possible values: + +```rust +fn main() { + let t = true; + let f: bool = false; // with explict type annotation +} +``` + +The main way to consume boolean values is through conditionals like `if`, which +we’ll see later in the chapter. + +## Characters + +We’ve only worked with numbers so far, but what about letters? Rust’s most +primitive alphabetic type is the `char`: + +```rust +fn main() { + let c = 'z'; + let z = 'ℤ'; +} +``` + +Rust’s `char` represents a [Unicode Scalar Value], which means that it can +represent a lot more than just ASCII. ‘Character’ isn’t really a concept in +Unicode, however: your human intutition for what a ‘character’ is may not match +up with a `char`. It also means that `char`s are four bytes each. + +[Unicode Scalar Value]: http://www.unicode.org/glossary/#unicode_scalar_value +# Compound Types + +Now that we’ve discussed scalar types, let’s talk about compound types. +These types can group multiple values of scalar types into another type. + +## Tuples + +We’ve seen tuples before, in the guise of binding or returning multiple values +at once. It turns out that there’s no magic here: tuples are a general way of +making a compound value that groups some number of other values with distinct +types. The number of values grouped is the ‘arity’ of the tuple. + +We create a tuple by writing a comma-separated list of values inside +parentheses; each position in the tuple has a distinct type: + +```rust +fn main() { + let tup: (i32, f64, u8) = (500, 6.4, 1); +} +``` + +Note that, unlike the examples of multiple bindings, here we bound the +single name `tup` to the entire tuple. We can then use pattern +matching to destructure this tuple value: + +```rust +fn main() { + let tup: (i32, f64, u8) = (500, 6.4, 1); + let (x, y, z) = tup; + + println!("The value of y is: {}", y); +} +``` + +Tuples are used sparingly in Rust code. This is because the elements of a tuple +are anonymous, which can make code hard to read. + +### Tuple indexing + +In addition to destructuring through pattern matching, we can also access a +tuple element directly using `.`, followed by the index we want to access: + +```rust +fn main() { + let x: (i32, f64, u8) = (500, 6.4, 1); + + let five_hundred = x.0; + let six_point_four = x.1; + let one = x.2; +} +``` + +As you can see, the first index is `0`. + +### Single-element tuples + +There’s one last trick with tuples: `(5)` is actually ambiguous: is it a tuple, +or is it a `5` in parethesis? If you need to disambiguate, use a comma: + +```rust +fn main() { + let x = (5); // x is an i32, no tuple. Think of it like (5 + 1) without the + 1, they’re for grouping. + + let x = (5,); // x is a (i32), a tuple with one element. +} +``` + +## Arrays + +So far, we’ve only represented single values in a binding. Sometimes, though, +it’s useful to have more than one value. These kinds of data structures are +called ‘collections’, and arrays are the ones we’ll learn about first. Arrays +look like this: + +```rust +fn main() { + let a = [1, 2, 3, 4, 5]; +} +``` + +An array’s type consists of the type of the elements it contains, as well as +the length: + +```rust +fn main() { + let a: [i32; 5] = [1, 2, 3, 4, 5]; +} +``` + +An array is a single chunk of memory, allocated on the stack. + +We can access elements of an array using indexing: + +```rust +fn main() { + let a = [1, 2, 3, 4, 5]; + + let first = a[0]; + let second = a[1]; +} +``` + +In this example, `first` will hold the value `1`, and `second` will be bound to +`2`. Note that these values are copied out of the array; if the array changes, +these bindings will not. Here’s an example, which also shows us how we can +modify elements of the array: + +```rust +fn main() { + let mut a = [1, 2, 3, 4, 5]; + + let first = a[0]; + + a[0] = 7; + + println!("The value of first is: {}", first); +} +``` + +Running this example will show that `first` is still `1`. If we didn’t want a +copy, but instead wanted to refer to the first element, whatever its value was, +we need a new concept. We’ll talk about ‘references’ in Section 4. + +One last thing: now that we are modifying the array, `a` needs to be declared +`mut`. + +Arrays are our first real data structure, and so there’s a few other concepts +that we haven’t covered in full yet. There are two: the `panic!` macro, and a +new way of printing things: `Debug`. + +### Panic + +We showed what happens when you access elements of an array, but what if we +give an invalid index? + +```rust,should_panic +fn main() { + let a = [1, 2, 3, 4, 5]; + + let invalid = a[10]; + + println!("The value of invalid is: {}", invalid); +} +``` + +If we run this example, we will get an error. Let’s re-use our `functions` +project from before. Change your `src/main.rs` to look like the example, and +run it: + +```bash +$ cargo run + Compiling functions v0.1.0 (file:///projects/functions) + Running `target/debug/functions` +thread ‘
’ panicked at ‘index out of bounds: the len is 5 but the index is 10’, src/main.rs:4 +Process didn’t exit successfully: `target/debug/functions` (exit code: 101) +``` + +It says that our thread panicked, and that our program didn’t exit +successfully. There’s also a reason: we had a length of five, but an index of +10. + +For now, all you need to know is that a panic will crash your program. Rust’s +error handling story is described in full in a later chapter. + +So why did this code panic? Well, arrays know how many elements they hold. When +we access an element via indexing, Rust will check that the index is less than +the length. If it’s greater, it will panic, as something is very wrong. This is +our first example of Rust’s safety principles in action. In many low-level +languages, this kind of check is not done. If you have an incorrect index, +invalid memory can be accessed. Rust protects us against this kind of error. + +### Debug + +So far, we’ve been printing values using `{}`. If we try that with an array, +though... + +```rust,ignore +fn main() { + let a = [1, 2, 3, 4, 5]; + + println!("a is: {}", a); +} +``` + +... we will get an error: + +```bash +$ cargo run + Compiling functions v0.1.0 (file:///projects/functions) +src/main.rs:4:25: 4:26 error: the trait `core::fmt::Display` is not implemented for the type `[_; 5]` [E0277] +src/main.rs:4 println!(“a is {}”, a); + ^ +: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:28 note: in this expansion of println! (defined in ) +src/main.rs:4:25: 4:26 help: run `rustc --explain E0277` to see a detailed explanation +src/main.rs:4:25: 4:26 note: `[_; 5]` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string +src/main.rs:4:25: 4:26 note: required by `core::fmt::Display::fmt` +error: aborting due to previous error +``` + +Whew! The core of the error is this part: the trait `core::fmt::Display` is not +implemented. We haven’t discussed traits yet, so this is bound to be confusing! +Here’s all we need to know for now: `println!` can do many kinds of formatting. +By default, `{}` implements a kind of formatting known as `Display`: output +intended for direct end-user consumption. The primitive types we’ve seen so far +implement `Display`, as there’s only one way you’d show a `1` to a user. But +with arrays, the output is less clear. Do you want commas or not? What about +the `[]`s? + +Due to these questions, more complex types in the standard library do not +implement `Display` formatting. There is another kind of formatting, `Debug`, +which is a bit different: intended for programmer consumption. We can ask +`println!` to use `Debug` formatting with `:?`: + +```rust +fn main() { + let a = [1, 2, 3, 4, 5]; + + println!("a is {:?}", a); +} +``` + +This will work: + +```bash +$ cargo run + Compiling functions v0.1.0 (file:///projects/functions) + Running `target/debug/functions` +a is [1, 2, 3, 4, 5] +``` + +You’ll see this repeated later, with other types. And we’ll cover traits fully +later in the book, Section 9. +# Comments + +We strive to make our programs easy to understand, but sometimes, some extra +explanation is warranted. We can leave notes in our source code that the +compiler will ignore. These notes are called ‘comments’. + +Here’s a comment: + +```rust +// Hello, world. +``` + +Comments start with two slashes, and last until the end of the line. Larger +comments will need more lines: + +```rust +// So we’re doing something complicated here, long enough that we need +// multiple lines of comments to do it! Whew! Hopefully, this comment will +// explain what’s going on. +``` + +Comments can also go at the end of lines: + +```rust +fn main() { + let lucky_number = 7; // I’m feeling lucky today. +} +``` + +But you’ll more often see them above: + +```rust +fn main() { + // I’m feeling lucky today. + let lucky_number = 7; +} +``` + +That’s all there is to it. Comments are not particularly complicated. + +## Documentation comments + +However, Rust has another kind of comment: a documentation comment. These +comments don’t affect the way that the code works, but they do work with Rust’s +tools. More specifically, the `rustdoc` tool that comes with Rust reads +documentation comments and produces HTML documentation from them. + +Documentation comments use an extra slash: + +```rust +/// The foo function doesn’t really do much. +fn foo() { +} + +/// We also can use +/// multiple comments here too, +/// like we did before +fn bar() { +} +``` + +This comment would then be interpreted by `rustdoc` as documenting the thing +that follows it: `foo()` and `bar()`. + +Because documentation comments have semantic meaning to `rustdoc`, the compiler +will pay attention to the placement of your documentation comments. For +example, a program with only this: + +```rust,ignore +/// What am I documenting? +``` + +Will give a compiler error: + +```text +src/main.rs:1:1: 1:27 error: expected item after doc comment +src/main.rs:1 /// What am I documenting? + ^~~~~~~~~~~~~~~~~~~~~~~~~~ +``` +# Control flow with `if` + +> Two roads diverged in a yellow wood, +> And sorry I could not travel both +> And be one traveler, long I stood +> And looked down one as far as I could +> To where it bent in the undergrowth; +> +> - Robert Frost, “The Road Not Taken” + +In Rust, there are a few ways to cause our code to branch. The most fundamental +way is by using `if`. An `if` expression gives us two paths forward, and asks +the question, “Which one should I take?” + +Let’s make a new project to explore `if`. Navigate to your projects directory, +and use Cargo to make a new project called `branches`: + +```bash +$ cargo new --bin branches +$ cd branches +``` + +Here’s a sample program using `if`: + +```rust +fn main() { + let condition = true; + + if condition { + println!("condition was true"); + } else { + println!("condition was false"); + } +} +``` + +Let's try running it: + +```bash +$ cargo run + Compiling branches v0.1.0 (file:///projects/branches) + Running `target/debug/branches` +condition was true +``` + +We can change the value of `condition`: + +```rust + let condition = false; +``` + +And then run it again: + +```bash +$ cargo run + Compiling branches v0.1.0 (file:///projects/branches) + Running `target/debug/branches` +condition was false +``` + +This is the very basic structure of `if`: _if_ the condition is true, then +execute some code. If it’s not true, then execute some other code, after +`else`. + +An `else` is not required: + +```rust +fn main() { + let condition = false; + + if condition { + println!("condition was true"); + } +} +``` + +In this case, nothing is printed. + +It’s also worth noting that `condition` here _must_ be a `bool`. Let’s try an +example with something else: + +```rust,ignore +fn main() { + let condition = 5; + + if condition { + println!("condition was five"); + } +} +``` + +If we try to run this program, Rust will complain: + +```bash + Compiling branches v0.1.0 (file:///projects/branches) +src/main.rs:4:8: 4:17 error: mismatched types: + expected `bool`, + found `_` +(expected bool, + found integral variable) [E0308] +src/main.rs:4 if condition { + ^~~~~~~~~ +src/main.rs:4:8: 4:17 help: run `rustc --explain E0308` to see a detailed explanation +error: aborting due to previous error +Could not compile `branches`. +``` + +We expected a `bool`, but got an integer. Rust will not automatically try to convert non-boolean types to a boolean here. We must be explicit. + +## `else if` + +We can make multiple decisions by combining `if` and `else` in another way: + +```rust +fn main() { + let number = 5; + + if number == 3 { + println!("condition was 3"); + } else if number == 4 { + println!("condition was 4"); + } else if number == 5 { + println!("condition was 5"); + } else { + println!("condition was something else"); + } +} +``` + +Let's try running it: + +```bash +$ cargo run + Compiling branches v0.1.0 (file:///projects/branches) + Running `target/debug/branches` +condition was 5 +``` + +When this program executes, it will check each `if` in turn, and execute the +first body for which the condition holds true. + +Using a single `else if` can be okay, but if you find yourself with more than one, +you may want to refactor your code. Rust has a more powerful branching construct +called `match` for these cases. We'll cover it later, when we talk about `enums`. + +## `if` as an expression + +There’s one last detail we need to learn about `if`: it’s an expression. That means +that we can use it on the right hand side of a `let` binding, for instance: + +```rust +fn main() { + let condition = true; + + let number = if condition { + 5 + } else { + 6 + }; + + println!("The value of number is: {}", number); +} +``` + +Let’s run this: + +```bash +$ cargo run + Compiling branches v0.1.0 (file:///projects/branches) + Running `target/debug/branches` +The value of number is: 5 +``` + +Remember, blocks of code evaluate to the last expression in them. And numbers +by themselves are also expressions. So in this case, the value of the whole +`if` expression depends on which block of code executes. + +There’s another small detail involved here: this means that if you use `if` +in this way, both arms of the `if` must be the same type. This doesn’t work: + +```rust,ignore +fn main() { + let condition = true; + + let number = if condition { + 5 + } else { + "six" + }; + + println!("The value of number is: {}", number); +} +``` + +If we try to run this, we’ll get an error: + +```bash + Compiling branches v0.1.0 (file:///projects/branches) +src/main.rs:4:18: 8:6 error: if and else have incompatible types: + expected `_`, + found `&‘static str` +(expected integral variable, + found &-ptr) [E0308] +src/main.rs:4 let number = if condition { +src/main.rs:5 5 +src/main.rs:6 } else { +src/main.rs:7 "six" +src/main.rs:8 }; +src/main.rs:4:18: 8:6 help: run `rustc --explain E0308` to see a detailed explanation +error: aborting due to previous error +Could not compile `branches`. +``` + +`if` and `else` have incompatible types. This can’t work. +# Loops + +It’s often quite useful to be able to execute a block of code more than one +time. For this, we have several constructs, called ‘loops’. + +To try out loops, let’s make a new project. Navigate to your projects folder +and use Cargo to make a new one: + +```bash +$ cargo new --bin loops +$ cd loops +``` + +There are three kinds of loops in Rust: `loop`, `while`, and `for`. Let’s dig +in. + +## `loop` + +The `loop` keyword is very straightforward: it executes a block of code over +and over and over and over and over and over forever. Change your `src/main.rs` +file to look like this: + +```rust,ignore +fn main() { + loop { + println!("again!"); + } +} +``` + +If we run this program, we’ll see ‘`again!`’ printed over and over again. So +how does our program end? It doesn’t, until we kill it. Most terminals support +a keyboard shortcut, ‘control-c’, to stop a runaway program. Give it a try: + +```bash +$ cargo run + Compiling loops v0.1.0 (file:///projects/loops) + Running `target/debug/loops` +again! +again! +again! +again! +^Cagain! +``` + +That `^C` there is where I hit control-c. + +That’s a lot of trouble though! Luckily, there’s a way to break an infinite `loop`. + +### Breaking out of a loop + +The `break` keyword will allow us to quit looping. Try this version out: + +```rust +fn main() { + loop { + println!("once!"); + break; + } +} +``` + +If you run this program with `cargo run`, you’ll see that it only executes one +time: + +```bash +$ cargo run + Compiling loops v0.1.0 (file:///projects/loops) + Running `target/debug/loops` +once! +``` + +When a Rust program hits a `break` statement, it will exit the current loop. + +## `while` + +What if we took `loop`, `break`, and `if`, and put them together? Something +like this: + +```rust +fn main() { + let mut number = 3; + + loop { + if number != 0 { + println!("{}!", number); + + number = number - 1; + } else { + break; + } + + } + + println!("LIFTOFF!!!"); +} +``` + +If we run this, we’ll get some output: + +```bash + Compiling loops v0.1.0 (file:///projects/loops) + Running `target/debug/loops` +3! +2! +1! +LIFTOFF!!! +``` + +The core of this example is in the combination of these three constructs: + +```rust,ignore + loop { + if number != 0 { + // do stuff + } else { + break; + } +``` + +We want to `loop`, but only while some sort of condition is true. As soon as it +isn't, we want to `break` out of the loop. + +This pattern is so common that we have a language construct for it: `while`. +Here's the same example, but using `while` instead: + +```rust +fn main() { + let mut number = 3; + while number != 0 { + println!("{}!", number); + + number = number - 1; + } + + println!("LIFTOFF!!!"); +} +``` + +This lets us get rid of a lot of nesting, and is more clear: while a condition holds, +run this code. + +## `for` + +We can use this `while` construct to loop over the elements of a collection, like an +array: + +```rust +fn main() { + let a = [1, 2, 3, 4, 5]; + let mut index = 0; + + while index < 5 { + println!("the value is is: {}", a[index]); + + index = index + 1; + } +} +``` + +Running this will print out every element of the array: + +```bash +$ cargo run + Compiling loops v0.1.0 (file:///projects/loops) + Running `target/debug/loops` +the value is: 1 +the value is: 2 +the value is: 3 +the value is: 4 +the value is: 5 +``` + +Here, we're counting up instead of down: we start at zero, then loop until we +hit the final index of our array. + +This approach is error-prone, though. If we get the index length incorrect, we +will end up causing a `panic!`. This is also slow, as the compiler needs to do +that check on every element on every iteration through the loop. + +Instead, we can use our last kind of loop: the `for` loop. It looks like this: + +```rust +fn main() { + let a = [1, 2, 3, 4, 5]; + let mut index = 0; + + for element in a.iter() { + println!("the value is: {}", element); + } +} +``` + +** NOTE: see [https://github.com/rust-lang/rust/issues/25725#issuecomment-166365658](https://github.com/rust-lang/rust/issues/25725#issuecomment-166365658), we may want to change this ** + +If we run this, we'll see the same output as the previous example. + +** I'm going to leave it at this for now until we decide how we want to do it**