]> git.proxmox.com Git - rustc.git/blob - src/doc/book/nostarch/chapter03.md
New upstream version 1.58.1+dfsg1
[rustc.git] / src / doc / book / nostarch / chapter03.md
1
2 [TOC]
3
4 # Common Programming Concepts
5
6 This chapter covers concepts that appear in almost every programming language
7 and how they work in Rust. Many programming languages have much in common at
8 their core. None of the concepts presented in this chapter are unique to Rust,
9 but we’ll discuss them in the context of Rust and explain the conventions
10 around using these concepts.
11
12 Specifically, you’ll learn about variables, basic types, functions, comments,
13 and control flow. These foundations will be in every Rust program, and learning
14 them early will give you a strong core to start from.
15
16 > #### Keywords
17 >
18 > The Rust language has a set of *keywords* that are reserved for use by
19 > the language only, much as in other languages. Keep in mind that you cannot
20 > use these words as names of variables or functions. Most of the keywords have
21 > special meanings, and you’ll be using them to do various tasks in your Rust
22 > programs; a few have no current functionality associated with them but have
23 > been reserved for functionality that might be added to Rust in the future. You
24 > can find a list of the keywords in Appendix A.
25
26 ## Variables and Mutability
27
28 As mentioned in the “Storing Values with Variables” section, by default
29 variables are immutable. This is one of many nudges Rust gives you to write
30 your code in a way that takes advantage of the safety and easy concurrency that
31 Rust offers. However, you still have the option to make your variables mutable.
32 Let’s explore how and why Rust encourages you to favor immutability and why
33 sometimes you might want to opt out.
34
35 When a variable is immutable, once a value is bound to a name, you can’t change
36 that value. To illustrate this, let’s generate a new project called *variables*
37 in your *projects* directory by using `cargo new variables`.
38
39 Then, in your new *variables* directory, open *src/main.rs* and replace its
40 code with the following code. This code won’t compile just yet, we'll first
41 examine the immutability error.
42
43 Filename: src/main.rs
44
45 ```
46 fn main() {
47 let x = 5;
48 println!("The value of x is: {}", x);
49 x = 6;
50 println!("The value of x is: {}", x);
51 }
52 ```
53
54 Save and run the program using `cargo run`. You should receive an error
55 message, as shown in this output:
56
57 ```
58 $ cargo run
59 Compiling variables v0.1.0 (file:///projects/variables)
60 error[E0384]: cannot assign twice to immutable variable `x`
61 --> src/main.rs:4:5
62 |
63 2 | let x = 5;
64 | -
65 | |
66 | first assignment to `x`
67 | help: consider making this binding mutable: `mut x`
68 3 | println!("The value of x is: {}", x);
69 4 | x = 6;
70 | ^^^^^ cannot assign twice to immutable variable
71 ```
72
73 This example shows how the compiler helps you find errors in your programs.
74 Compiler errors can be frustrating, but really they only mean your program
75 isn’t safely doing what you want it to do yet; they do *not* mean that you’re
76 not a good programmer! Experienced Rustaceans still get compiler errors.
77
78 The error message indicates that the cause of the error is that you `` cannot
79 assign twice to immutable variable `x` ``, because you tried to assign a second
80 value to the immutable `x` variable.
81
82 It’s important that we get compile-time errors when we attempt to change a
83 value that’s designated as immutable because this very situation can lead to
84 bugs. If one part of our code operates on the assumption that a value will
85 never change and another part of our code changes that value, it’s possible
86 that the first part of the code won’t do what it was designed to do. The cause
87 of this kind of bug can be difficult to track down after the fact, especially
88 when the second piece of code changes the value only *sometimes*. The Rust
89 compiler guarantees that when you state a value won’t change, it really won’t
90 change, so you don’t have to keep track of it yourself. Your code is thus
91 easier to reason through.
92
93 But mutability can be very useful, and can make code more convenient to write.
94 Variables are immutable only by default; as you did in Chapter 2, you can make
95 them mutable by adding `mut` in front of the variable name. Adding `mut` also
96 conveys intent to future readers of the code by indicating that other parts of
97 the code will be changing this variable’s value.
98
99 For example, let’s change *src/main.rs* to the following:
100
101 Filename: src/main.rs
102
103 ```
104 fn main() {
105 let mut x = 5;
106 println!("The value of x is: {}", x);
107 x = 6;
108 println!("The value of x is: {}", x);
109 }
110 ```
111
112 When we run the program now, we get this:
113
114 ```
115 $ cargo run
116 Compiling variables v0.1.0 (file:///projects/variables)
117 Finished dev [unoptimized + debuginfo] target(s) in 0.30s
118 Running `target/debug/variables`
119 The value of x is: 5
120 The value of x is: 6
121 ```
122
123 We’re allowed to change the value that `x` binds to from `5` to `6` when `mut`
124 is used. There are multiple trade-offs to consider in addition to the
125 prevention of bugs. For example, in cases where you’re using large data
126 structures, mutating an instance in place may be faster than copying and
127 returning newly allocated instances. With smaller data structures, creating new
128 instances and writing in a more functional programming style may be easier to
129 think through, so lower performance might be a worthwhile penalty for gaining
130 that clarity.
131
132 ### Constants
133
134 Like immutable variables, *constants* are values that are bound to a name and
135 are not allowed to change, but there are a few differences between constants
136 and variables.
137
138 First, you aren’t allowed to use `mut` with constants. Constants aren’t just
139 immutable by default—they’re always immutable. You declare constants using the
140 `const` keyword instead of the `let` keyword, and the type of the value *must*
141 be annotated. We’re about to cover types and type annotations in the next
142 section, “Data Types,” so don’t worry about the details right now. Just know
143 that you must always annotate the type.
144
145 Constants can be declared in any scope, including the global scope, which makes
146 them useful for values that many parts of code need to know about.
147
148 The last difference is that constants may be set only to a constant expression,
149 not the result of a value that could only be computed at runtime.
150
151 Here’s an example of a constant declaration:
152
153 ```
154 const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;
155 ```
156
157 The constant’s name is `THREE_HOURS_IN_SECONDS` and its value is set to the
158 result of multiplying 60 (the number of seconds in a minute) by 60 (the number
159 of minutes in an hour) by 3 (the number of hours we want to count in this
160 program). Rust’s naming convention for constants is to use all uppercase with
161 underscores between words. The compiler is able to evaluate a limited set of
162 operations at compile time, which lets us choose to write out this value in a
163 way that’s easier to understand and verify, rather than setting this constant
164 to the value 10,800. See the Rust Reference’s section on constant evaluation at
165 *https://doc.rust-lang.org/reference/const_eval.html* for more information on
166 what operations can be used when declaring constants.
167
168 Constants are valid for the entire time a program runs, within the scope they
169 were declared in. This property makes constants useful for values in your
170 application domain that multiple parts of the program might need to know about,
171 such as the maximum number of points any player of a game is allowed to earn or
172 the speed of light.
173
174 Naming hardcoded values used throughout your program as constants is useful in
175 conveying the meaning of that value to future maintainers of the code. It also
176 helps to have only one place in your code you would need to change if the
177 hardcoded value needed to be updated in the future.
178
179 ### Shadowing
180
181 As you saw in the guessing game tutorial in Chapter 2, you can declare a new
182 variable with the same name as a previous variable. Rustaceans say that the
183 first variable is *shadowed* by the second, which means that the second
184 variable’s value is what the program sees when the variable is used. We can
185 shadow a variable by using the same variable’s name and repeating the use of
186 the `let` keyword as follows:
187
188 Filename: src/main.rs
189
190 ```
191 fn main() {
192 let x = 5;
193
194 let x = x + 1;
195
196 {
197 let x = x * 2;
198 println!("The value of x in the inner scope is: {}", x);
199 }
200
201 println!("The value of x is: {}", x);
202 }
203 ```
204
205 This program first binds `x` to a value of `5`. Then it shadows `x` by
206 repeating `let x =`, taking the original value and adding `1` so the value of
207 `x` is then `6`. Then, within an inner scope, the third `let` statement also
208 shadows `x`, multiplying the previous value by `2` to give `x` a value of `12`.
209 When that scope is over, the inner shadowing ends and `x` returns to being `6`.
210 When we run this program, it will output the following:
211
212 ```
213 $ cargo run
214 Compiling variables v0.1.0 (file:///projects/variables)
215 Finished dev [unoptimized + debuginfo] target(s) in 0.31s
216 Running `target/debug/variables`
217 The value of x in the inner scope is: 12
218 The value of x is: 6
219 ```
220
221 Shadowing is different from marking a variable as `mut`, because we’ll get a
222 compile-time error if we accidentally try to reassign to this variable without
223 using the `let` keyword. By using `let`, we can perform a few transformations
224 on a value but have the variable be immutable after those transformations have
225 been completed.
226
227 <!--- so, to be clear, we're not overwriting the variable, so when the
228 shadowing variable goes out of scope the earlier variables become visible to
229 the compiler? --->
230 <!-- Well, we *are* overwriting it *in the inner scope* -- there's no way to
231 access the original value from the outer scope within the inner scope after
232 the shadowing. But yes, shadowing only applies to the scope it happens in,
233 which is what this example illustrates. Is there something that could be
234 made clearer? /Carol -->
235
236 The other difference between `mut` and shadowing is that because we’re
237 effectively creating a new variable when we use the `let` keyword again, we can
238 change the type of the value but reuse the same name. For example, say our
239 program asks a user to show how many spaces they want between some text by
240 inputting space characters, and then we want to store that input as a number:
241
242 ```
243 let spaces = " ";
244 let spaces = spaces.len();
245 ```
246
247 The first `spaces` variable is a string type and the second `spaces` variable
248 is a number type. Shadowing thus spares us from having to come up with
249 different names, such as `spaces_str` and `spaces_num`; instead, we can reuse
250 the simpler `spaces` name. However, if we try to use `mut` for this, as shown
251 here, we’ll get a compile-time error:
252
253 ```
254 let mut spaces = " ";
255 spaces = spaces.len();
256 ```
257
258 The error says we’re not allowed to mutate a variable’s type:
259
260 ```
261 $ cargo run
262 Compiling variables v0.1.0 (file:///projects/variables)
263 error[E0308]: mismatched types
264 --> src/main.rs:3:14
265 |
266 3 | spaces = spaces.len();
267 | ^^^^^^^^^^^^ expected `&str`, found `usize`
268 ```
269
270 Now that we’ve explored how variables work, let’s look at more data types they
271 can have.
272
273 ## Data Types
274
275 Every value in Rust is of a certain *data type*, which tells Rust what kind of
276 data is being specified so it knows how to work with that data. We’ll look at
277 two data type subsets: scalar and compound.
278
279 Keep in mind that Rust is a *statically typed* language, which means that it
280 must know the types of all variables at compile time. The compiler can usually
281 infer what type we want to use based on the value and how we use it. In cases
282 when many types are possible, such as when we converted a `String` to a numeric
283 type using `parse` in the “Comparing the Guess to the Secret Number” section in
284 Chapter 2, we must add a type annotation, like this:
285
286 ```
287 let guess: u32 = "42".parse().expect("Not a number!");
288 ```
289
290 If we don’t add the type annotation here, Rust will display the following
291 error, which means the compiler needs more information from us to know which
292 type we want to use:
293
294 ```
295 $ cargo build
296 Compiling no_type_annotations v0.1.0 (file:///projects/no_type_annotations)
297 error[E0282]: type annotations needed
298 --> src/main.rs:2:9
299 |
300 2 | let guess = "42".parse().expect("Not a number!");
301 | ^^^^^ consider giving `guess` a type
302 ```
303
304 You’ll see different type annotations for other data types.
305
306 ### Scalar Types
307
308 A *scalar* type represents a single value. Rust has four primary scalar types:
309 integers, floating-point numbers, Booleans, and characters. You may recognize
310 these from other programming languages. Let’s jump into how they work in Rust.
311
312 #### Integer Types
313
314 An *integer* is a number without a fractional component. We used one integer
315 type in Chapter 2, the `u32` type. This type declaration indicates that the
316 value it’s associated with should be an unsigned integer (signed integer types
317 start with `i`, instead of `u`) that takes up 32 bits of space. Table 3-1 shows
318 the built-in integer types in Rust. We can use any of these variants to declare
319 the type of an integer value.
320
321 Table 3-1: Integer Types in Rust
322
323 | Length | Signed | Unsigned |
324 |---------|---------|----------|
325 | 8-bit | `i8` | `u8` |
326 | 16-bit | `i16` | `u16` |
327 | 32-bit | `i32` | `u32` |
328 | 64-bit | `i64` | `u64` |
329 | 128-bit | `i128` | `u128` |
330 | arch | `isize` | `usize` |
331
332 Each variant can be either signed or unsigned and has an explicit size.
333 *Signed* and *unsigned* refer to whether it’s possible for the number to be
334 negative—in other words, whether the number needs to have a sign with it
335 (signed) or whether it will only ever be positive and can therefore be
336 represented without a sign (unsigned). It’s like writing numbers on paper: when
337 the sign matters, a number is shown with a plus sign or a minus sign; however,
338 when it’s safe to assume the number is positive, it’s shown with no sign.
339 Signed numbers are stored using two’s complement representation.
340
341 Each signed variant can store numbers from -(2<sup>n - 1</sup>) to 2<sup>n -
342 1</sup> - 1 inclusive, where *n* is the number of bits that variant uses. So an
343 `i8` can store numbers from -(2<sup>7</sup>) to 2<sup>7</sup> - 1, which equals
344 -128 to 127. Unsigned variants can store numbers from 0 to 2<sup>n</sup> - 1,
345 so a `u8` can store numbers from 0 to 2<sup>8</sup> - 1, which equals 0 to 255.
346
347 Additionally, the `isize` and `usize` types depend on the architecture of the
348 computer your program is running on, which is denoted in the table as "arch":
349 64 bits if you’re on a 64-bit architecture and 32 bits if you’re on a 32-bit
350 architecture.
351
352 <!--- what does arch refer to? /LC --->
353 <!-- architecture-dependent, I've tried to specifically make that connection,
354 is this better? /Carol -->
355
356 You can write integer literals in any of the forms shown in Table 3-2. Note
357 that number literals that can be multiple numeric types allow a type suffix,
358 such as `57u8`, to designate the type. Number literals can also use `_` as a
359 visual separator to make the number easier to read, such as `1_000`, which will
360 have the same value as if you had specified `1000`.
361
362 Table 3-2: Integer Literals in Rust
363
364 | Number literals | Example |
365 |------------------|---------------|
366 | Decimal | `98_222` |
367 | Hex | `0xff` |
368 | Octal | `0o77` |
369 | Binary | `0b1111_0000` |
370 | Byte (`u8` only) | `b'A'` |
371
372 So how do you know which type of integer to use? If you’re unsure, Rust’s
373 defaults are generally good places to start: integer types default to `i32`.
374 The primary situation in which you’d use `isize` or `usize` is when indexing
375 some sort of collection.
376
377 > ##### Integer Overflow
378 >
379 > Let’s say you have a variable of type `u8` that can hold values between 0 and
380 > 255. If you try to change the variable to a value outside of that range, such
381 > as 256, *integer overflow* will occur, which can result in one of two
382 > behaviors. When you’re compiling in debug mode, Rust includes checks for
383 > integer overflow that cause your program to *panic* at runtime if this
384 > behavior occurs. Rust uses the term panicking when a program exits with an
385 > error; we’ll discuss panics in more depth in the “Unrecoverable Errors with
386 > `panic!`” section in Chapter 9.
387 >
388 > When you’re compiling in release mode with the `--release` flag, Rust does
389 > *not* include checks for integer overflow that cause panics. Instead, if
390 > overflow occurs, Rust performs *two’s complement wrapping*. In short, values
391 > greater than the maximum value the type can hold “wrap around” to the minimum
392 > of the values the type can hold. In the case of a `u8`, the value 256 becomes
393 > 0, the value 257 becomes 1, and so on. The program won’t panic, but the
394 > variable will have a value that probably isn’t what you were expecting it to
395 > have. Relying on integer overflow’s wrapping behavior is considered an error.
396 >
397 > To explicitly handle the possibility of overflow, you can use these families
398 > of methods provided by the standard library for primitive numeric types:
399 >
400 > - Wrap in all modes with the `wrapping_*` methods, such as `wrapping_add`
401 > - Return the `None` value if there is overflow with the `checked_*` methods
402 > - Return the value and a boolean indicating whether there was overflow with
403 > the `overflowing_*` methods
404 > - Saturate at the value’s minimum or maximum values with `saturating_*`
405 > methods
406
407 #### Floating-Point Types
408
409 Rust also has two primitive types for *floating-point numbers*, which are
410 numbers with decimal points. Rust’s floating-point types are `f32` and `f64`,
411 which are 32 bits and 64 bits in size, respectively. The default type is `f64`
412 because on modern CPUs it’s roughly the same speed as `f32` but is capable of
413 more precision. All floating-point types are signed.
414
415 <!--- and these don't need to be designate as signed or unsigned? /LC --->
416 <!-- Yes, it's a long story why, I've added a quick statement as such at the
417 end of the previous paragraph, does that work? /Carol-->
418
419 Here’s an example that shows floating-point numbers in action:
420
421 Filename: src/main.rs
422
423 ```
424 fn main() {
425 let x = 2.0; // f64
426
427 let y: f32 = 3.0; // f32
428 }
429 ```
430
431 Floating-point numbers are represented according to the IEEE-754 standard. The
432 `f32` type is a single-precision float, and `f64` has double precision.
433
434 #### Numeric Operations
435
436 Rust supports the basic mathematical operations you’d expect for all of the
437 number types: addition, subtraction, multiplication, division, and remainder.
438 Integer division rounds down to the nearest integer. The following code shows
439 how you’d use each numeric operation in a `let` statement:
440
441 Filename: src/main.rs
442
443 ```
444 fn main() {
445 // addition
446 let sum = 5 + 10;
447
448 // subtraction
449 let difference = 95.5 - 4.3;
450
451 // multiplication
452 let product = 4 * 30;
453
454 // division
455 let quotient = 56.7 / 32.2;
456 let floored = 2 / 3; // Results in 0
457
458 // remainder
459 let remainder = 43 % 5;
460 }
461 ```
462
463 Each expression in these statements uses a mathematical operator and evaluates
464 to a single value, which is then bound to a variable. Appendix B contains a
465 list of all operators that Rust provides.
466
467 #### The Boolean Type
468
469 As in most other programming languages, a Boolean type in Rust has two possible
470 values: `true` and `false`. Booleans are one byte in size. The Boolean type in
471 Rust is specified using `bool`. For example:
472
473 Filename: src/main.rs
474
475 ```
476 fn main() {
477 let t = true;
478
479 let f: bool = false; // with explicit type annotation
480 }
481 ```
482
483 The main way to use Boolean values is through conditionals, such as an `if`
484 expression. We’ll cover how `if` expressions work in Rust in the “Control
485 Flow” section.
486
487 #### The Character Type
488
489 Rust’s `char` type is the language’s most primitive alphabetic type. Here's
490 some examples of declaring `char` values:
491
492 Filename: src/main.rs
493
494 ```
495 fn main() {
496 let c = 'z';
497 let z = 'ℤ';
498 let heart_eyed_cat = '😻';
499 }
500 ```
501
502 Note that we specify `char` literals with single quotes, as opposed to string
503 literals, which use double quotes. Rust’s `char` type is four bytes in size and
504 represents a Unicode Scalar Value, which means it can represent a lot more than
505 just ASCII. Accented letters; Chinese, Japanese, and Korean characters; emoji;
506 and zero-width spaces are all valid `char` values in Rust. Unicode Scalar
507 Values range from `U+0000` to `U+D7FF` and `U+E000` to `U+10FFFF` inclusive.
508 However, a “character” isn’t really a concept in Unicode, so your human
509 intuition for what a “character” is may not match up with what a `char` is in
510 Rust. We’ll discuss this topic in detail in “Storing UTF-8 Encoded Text with
511 Strings” in Chapter 8.
512
513 ### Compound Types
514
515 *Compound types* can group multiple values into one type. Rust has two
516 primitive compound types: tuples and arrays.
517
518 #### The Tuple Type
519
520 A tuple is a general way of grouping together a number of values with a variety
521 of types into one compound type. Tuples have a fixed length: once declared,
522 they cannot grow or shrink in size.
523
524 We create a tuple by writing a comma-separated list of values inside
525 parentheses. Each position in the tuple has a type, and the types of the
526 different values in the tuple don’t have to be the same. We’ve added optional
527 type annotations in this example:
528
529 Filename: src/main.rs
530
531 ```
532 fn main() {
533 let tup: (i32, f64, u8) = (500, 6.4, 1);
534 }
535 ```
536
537 The variable `tup` binds to the entire tuple, because a tuple is considered a
538 single compound element. To get the individual values out of a tuple, we can
539 use pattern matching to destructure a tuple value, like this:
540
541 Filename: src/main.rs
542
543 ```
544 fn main() {
545 let tup = (500, 6.4, 1);
546
547 let (x, y, z) = tup;
548
549 println!("The value of y is: {}", y);
550 }
551 ```
552
553 This program first creates a tuple and binds it to the variable `tup`. It then
554 uses a pattern with `let` to take `tup` and turn it into three separate
555 variables, `x`, `y`, and `z`. This is called *destructuring*, because it breaks
556 the single tuple into three parts. Finally, the program prints the value of
557 `y`, which is `6.4`.
558
559 We can also access a tuple element directly by using a period (`.`) followed by
560 the index of the value we want to access. For example:
561
562 Filename: src/main.rs
563
564 ```
565 fn main() {
566 let x: (i32, f64, u8) = (500, 6.4, 1);
567
568 let five_hundred = x.0;
569
570 let six_point_four = x.1;
571
572 let one = x.2;
573 }
574 ```
575
576 This program creates the tuple `x` and then makes new variables for each
577 element by using their respective indices. As with most programming languages,
578 the first index in a tuple is 0.
579
580 The tuple without any values, `()`, is a special type that has only one value,
581 also written `()`. The type is called the *unit type* and the value is called
582 the *unit value*. Expressions implicitly return the unit value if they don’t
583 return any other value.
584
585 #### The Array Type
586
587 Another way to have a collection of multiple values is with an *array*. Unlike
588 a tuple, every element of an array must have the same type. Unlike arrays in
589 some other languages, arrays in Rust have a fixed length.
590
591 We write the values in an array as a comma-separated list inside square
592 brackets:
593
594 Filename: src/main.rs
595
596 ```
597 fn main() {
598 let a = [1, 2, 3, 4, 5];
599 }
600 ```
601
602 Arrays are useful when you want your data allocated on the stack rather than
603 the heap (we will discuss the stack and the heap more in Chapter 4) or when you
604 want to ensure you always have a fixed number of elements. An array isn’t as
605 flexible as the vector type, though. A vector is a similar collection type
606 provided by the standard library that *is* allowed to grow or shrink in size.
607 If you’re unsure whether to use an array or a vector, chances are you should
608 use a vector. Chapter 8 discusses vectors in more detail.
609
610 However, arrays are more useful when you know the number of elements will not
611 need to change. For example, if you were using the names of the month in a
612 program, you would probably use an array rather than a vector because you know
613 it will always contain 12 elements:
614
615 ```
616 let months = ["January", "February", "March", "April", "May", "June", "July",
617 "August", "September", "October", "November", "December"];
618 ```
619
620 <!--- and is the benefit here that using the array prevents other coders making
621 the mistake of somehow changing the values, while with a vector they could?
622 /LC --->
623 <!-- No, the benefit is that you know there will always be 12 elements in the
624 array. Arrays can be mutable in that other parts of the code could change
625 "January" to "Jan", but they couldn't add or remove a month. Does that make
626 sense? I've changed the paragraph before the code to say "number of elements"
627 instead of "values", does that clear it up? /Carol -->
628
629 You write an array’s type using square brackets with the type of each element,
630 a semicolon, and then the number of elements in the array, like so:
631
632 ```
633 let a: [i32; 5] = [1, 2, 3, 4, 5];
634 ```
635
636 Here, `i32` is the type of each element. After the semicolon, the number `5`
637 indicates the array contains five elements.
638
639 You can also initialize an array to contain the same value for each element by
640 specifying the initial value, followed by a semicolon, and then the length of
641 the array in square brackets, as shown here:
642
643 ```
644 let a = [3; 5];
645 ```
646
647 The array named `a` will contain `5` elements that will all be set to the value
648 `3` initially. This is the same as writing `let a = [3, 3, 3, 3, 3];` but in a
649 more concise way.
650
651 ##### Accessing Array Elements
652
653 An array is a single chunk of memory of a known, fixed size that can be
654 allocated on the stack. You can access elements of an array using indexing,
655 like this:
656
657 Filename: src/main.rs
658
659 ```
660 fn main() {
661 let a = [1, 2, 3, 4, 5];
662
663 let first = a[0];
664 let second = a[1];
665 }
666 ```
667
668 In this example, the variable named `first` will get the value `1`, because
669 that is the value at index `[0]` in the array. The variable named `second` will
670 get the value `2` from index `[1]` in the array.
671
672 ##### Invalid Array Element Access
673
674 Let's see what happens if you try to access an element of an array that is past
675 the end of the array. Say you run this code, similar to the guessing game in
676 Chapter 2, to get an array index from the user:
677
678 Filename: src/main.rs
679
680 ```
681 use std::io;
682
683 fn main() {
684 let a = [1, 2, 3, 4, 5];
685
686 println!("Please enter an array index.");
687
688 let mut index = String::new();
689
690 io::stdin()
691 .read_line(&mut index)
692 .expect("Failed to read line");
693
694 let index: usize = index
695 .trim()
696 .parse()
697 .expect("Index entered was not a number");
698
699 let element = a[index];
700
701 println!(
702 "The value of the element at index {} is: {}",
703 index, element
704 );
705 }
706 ```
707
708 This code compiles successfully. If you run this code using `cargo run` and
709 enter 0, 1, 2, 3, or 4, the program will print out the corresponding value at
710 that index in the array. If you instead enter a number past the end of the
711 array, such as 10, you’ll see output like this:
712
713 ```
714 thread 'main' panicked at 'index out of bounds: the len is 5 but the index is 10', src/main.rs:19:19
715 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
716 ```
717
718 The program resulted in a *runtime* error at the point of using an invalid
719 value in the indexing operation. The program exited with an error message and
720 didn’t execute the final `println!` statement. When you attempt to access an
721 element using indexing, Rust will check that the index you’ve specified is less
722 than the array length. If the index is greater than or equal to the length,
723 Rust will panic. This check has to happen at runtime, especially in this case,
724 because the compiler can’t possibly know what value a user will enter when they
725 run the code later.
726
727 This is an example of Rust’s memory safety principles in action. In many
728 low-level languages, this kind of check is not done, and when you provide an
729 incorrect index, invalid memory can be accessed. Rust protects you against this
730 kind of error by immediately exiting instead of allowing the memory access and
731 continuing. Chapter 9 discusses more of Rust’s error handling.
732
733 ## Functions
734
735 Functions are prevalent in Rust code. You’ve already seen one of the most
736 important functions in the language: the `main` function, which is the entry
737 point of many programs. You’ve also seen the `fn` keyword, which allows you to
738 declare new functions.
739
740 Rust code uses *snake case* as the conventional style for function and variable
741 names, in which all letters are lowercase and underscores separate words.
742 Here’s a program that contains an example function definition:
743
744 Filename: src/main.rs
745
746 ```
747 fn main() {
748 println!("Hello, world!");
749
750 another_function();
751 }
752
753 fn another_function() {
754 println!("Another function.");
755 }
756 ```
757
758 We define a function in Rust by entering `fn` followed by a function name and a
759 set of parentheses. The curly brackets tell the compiler where the function
760 body begins and ends.
761
762 We can call any function we’ve defined by entering its name followed by a set
763 of parentheses. Because `another_function` is defined in the program, it can be
764 called from inside the `main` function. Note that we defined `another_function`
765 *after* the `main` function in the source code; we could have defined it before
766 as well. Rust doesn’t care where you define your functions, only that they’re
767 defined somewhere.
768
769 Let’s start a new binary project named *functions* to explore functions
770 further. Place the `another_function` example in *src/main.rs* and run it. You
771 should see the following output:
772
773 ```
774 $ cargo run
775 Compiling functions v0.1.0 (file:///projects/functions)
776 Finished dev [unoptimized + debuginfo] target(s) in 0.28s
777 Running `target/debug/functions`
778 Hello, world!
779 Another function.
780 ```
781
782 The lines execute in the order in which they appear in the `main` function.
783 First, the “Hello, world!” message prints, and then `another_function` is
784 called and its message is printed.
785
786 ### Parameters
787
788 We can define functions to have *parameters*, which are special variables that
789 are part of a function’s signature. When a function has parameters, you can
790 provide it with concrete values for those parameters. Technically, the concrete
791 values are called *arguments*, but in casual conversation, people tend to use
792 the words *parameter* and *argument* interchangeably for either the variables
793 in a function’s definition or the concrete values passed in when you call a
794 function.
795
796 In this version of `another_function` we add a parameter:
797
798 Filename: src/main.rs
799
800 ```
801 fn main() {
802 another_function(5);
803 }
804
805 fn another_function(x: i32) {
806 println!("The value of x is: {}", x);
807 }
808 ```
809
810 Try running this program; you should get the following output:
811
812 ```
813 $ cargo run
814 Compiling functions v0.1.0 (file:///projects/functions)
815 Finished dev [unoptimized + debuginfo] target(s) in 1.21s
816 Running `target/debug/functions`
817 The value of x is: 5
818 ```
819
820 The declaration of `another_function` has one parameter named `x`. The type of
821 `x` is specified as `i32`. When we pass `5` in to `another_function`, the
822 `println!` macro puts `5` where the pair of curly brackets were in the format
823 string.
824
825 In function signatures, you *must* declare the type of each parameter. This is
826 a deliberate decision in Rust’s design: requiring type annotations in function
827 definitions means the compiler almost never needs you to use them elsewhere in
828 the code to figure out what type you mean.
829
830 When defining multiple parameters, separate the parameter declarations with
831 commas, like this:
832
833 Filename: src/main.rs
834
835 ```
836 fn main() {
837 print_labeled_measurement(5, 'h');
838 }
839
840 fn print_labeled_measurement(value: i32, unit_label: char) {
841 println!("The measurement is: {}{}", value, unit_label);
842 }
843 ```
844
845 This example creates a function named `print_labeled_measurement` with two
846 parameters. The first parameter is named `value` and is an `i32`. The second is
847 named `unit_label` and is type `char`. The function then prints text containing
848 both the `value` and the `unit_label`.
849
850 Let’s try running this code. Replace the program currently in your *functions*
851 project’s *src/main.rs* file with the preceding example and run it using `cargo
852 run`:
853
854 ```
855 $ cargo run
856 Compiling functions v0.1.0 (file:///projects/functions)
857 Finished dev [unoptimized + debuginfo] target(s) in 0.31s
858 Running `target/debug/functions`
859 The measurement is: 5h
860 ```
861
862 Because we called the function with `5` as the value for `value` and `'h'` as
863 the value for `unit_label`, the program output contains those values.
864
865 ### Statements and Expressions
866
867 Function bodies are made up of a series of statements optionally ending in an
868 expression. So far, the functions we've covered haven't included an ending
869 expression, but you have seen an expression as part of a statement. Because
870 Rust is an expression-based language, this is an important distinction to
871 understand. Other languages don’t have the same distinctions, so let’s look at
872 what statements and expressions are and how their differences affect the bodies
873 of functions.
874
875 *Statements* are instructions that perform some action and do not return a
876 value. *Expressions* evaluate to a resulting value. Let’s look at some examples.
877
878 We’ve actually already used statements and expressions. Creating a variable and
879 assigning a value to it with the `let` keyword is a statement. In Listing 3-1,
880 `let y = 6;` is a statement.
881
882 Filename: src/main.rs
883
884 ```
885 fn main() {
886 let y = 6;
887 }
888 ```
889
890 Listing 3-1: A `main` function declaration containing one statement
891
892 Function definitions are also statements; the entire preceding example is a
893 statement in itself.
894
895 Statements do not return values. Therefore, you can’t assign a `let` statement
896 to another variable, as the following code tries to do; you’ll get an error:
897
898 Filename: src/main.rs
899
900 ```
901 fn main() {
902 let x = (let y = 6);
903 }
904 ```
905
906 When you run this program, the error you’ll get looks like this:
907
908 ```
909 $ cargo run
910 Compiling functions v0.1.0 (file:///projects/functions)
911 error[E0658]: `let` expressions in this position are experimental
912 --> src/main.rs:2:14
913 |
914 2 | let x = (let y = 6);
915 | ^^^^^^^^^
916 |
917 = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
918 = help: you can write `matches!(<expr>, <pattern>)` instead of `let <pattern> = <expr>`
919
920 error: expected expression, found statement (`let`)
921 --> src/main.rs:2:14
922 |
923 2 | let x = (let y = 6);
924 | ^^^^^^^^^
925 |
926 = note: variable declaration using `let` is a statement
927
928 warning: unnecessary parentheses around assigned value
929 --> src/main.rs:2:13
930 |
931 2 | let x = (let y = 6);
932 | ^^^^^^^^^^^ help: remove these parentheses
933 |
934 = note: `#[warn(unused_parens)]` on by default
935 ```
936
937 The `let y = 6` statement does not return a value, so there isn’t anything for
938 `x` to bind to. This is different from what happens in other languages, such as
939 C and Ruby, where the assignment returns the value of the assignment. In those
940 languages, you can write `x = y = 6` and have both `x` and `y` have the value
941 `6`; that is not the case in Rust.
942
943 Expressions evaluate to a value and make up most of the rest of the code that
944 you’ll write in Rust. Consider a math operation, such as `5 + 6`, which is an
945 expression that evaluates to the value `11`. Expressions can be part of
946 statements: in Listing 3-1, the `6` in the statement `let y = 6;` is an
947 expression that evaluates to the value `6`. Calling a function is an
948 expression. Calling a macro is an expression. A new scope block created with
949 curly brackets is an expression, for example:
950
951 Filename: src/main.rs
952
953 ```
954 fn main() {
955 let x = 5;
956
957 let y = {
958 let x = 3;
959 x + 1
960 };
961
962 println!("The value of y is: {}", y);
963 }
964 ```
965
966 This expression:
967
968 ```
969 {
970 let x = 3;
971 x + 1
972 }
973 ```
974
975 is a block that, in this case, evaluates to `4`. That value gets bound to `y`
976 as part of the `let` statement. Note that the `x + 1` line doesn't have a
977 semicolon at the end, unlike most of the lines you’ve seen so far. Expressions
978 do not include ending semicolons. If you add a semicolon to the end of an
979 expression, you turn it into a statement, and it will then not return a value.
980 Keep this in mind as you explore function return values and expressions next.
981
982 ### Functions with Return Values
983
984 Functions can return values to the code that calls them. We don’t name return
985 values, but we do declare their type after an arrow (`->`). In Rust, the return
986 value of the function is synonymous with the value of the final expression in
987 the block of the body of a function. You can return early from a function by
988 using the `return` keyword and specifying a value, but most functions return
989 the last expression implicitly. Here’s an example of a function that returns a
990 value:
991
992 Filename: src/main.rs
993
994 ```
995 fn five() -> i32 {
996 5
997 }
998
999 fn main() {
1000 let x = five();
1001
1002 println!("The value of x is: {}", x);
1003 }
1004 ```
1005
1006 There are no function calls, macros, or even `let` statements in the `five`
1007 function—just the number `5` by itself. That’s a perfectly valid function in
1008 Rust. Note that the function’s return type is specified too, as `-> i32`. Try
1009 running this code; the output should look like this:
1010
1011 ```
1012 $ cargo run
1013 Compiling functions v0.1.0 (file:///projects/functions)
1014 Finished dev [unoptimized + debuginfo] target(s) in 0.30s
1015 Running `target/debug/functions`
1016 The value of x is: 5
1017 ```
1018
1019 The `5` in `five` is the function’s return value, which is why the return type
1020 is `i32`. Let’s examine this in more detail. There are two important bits:
1021 first, the line `let x = five();` shows that we’re using the return value of a
1022 function to initialize a variable. Because the function `five` returns a `5`,
1023 that line is the same as the following:
1024
1025 ```
1026 let x = 5;
1027 ```
1028
1029 Second, the `five` function has no parameters and defines the type of the
1030 return value, but the body of the function is a lonely `5` with no semicolon
1031 because it’s an expression whose value we want to return.
1032
1033 Let’s look at another example:
1034
1035 Filename: src/main.rs
1036
1037 ```
1038 fn main() {
1039 let x = plus_one(5);
1040
1041 println!("The value of x is: {}", x);
1042 }
1043
1044 fn plus_one(x: i32) -> i32 {
1045 x + 1
1046 }
1047 ```
1048
1049 Running this code will print `The value of x is: 6`. But if we place a
1050 semicolon at the end of the line containing `x + 1`, changing it from an
1051 expression to a statement, we’ll get an error.
1052
1053 Filename: src/main.rs
1054
1055 ```
1056 fn main() {
1057 let x = plus_one(5);
1058
1059 println!("The value of x is: {}", x);
1060 }
1061
1062 fn plus_one(x: i32) -> i32 {
1063 x + 1;
1064 }
1065 ```
1066
1067 Compiling this code produces an error, as follows:
1068
1069 ```
1070 $ cargo run
1071 Compiling functions v0.1.0 (file:///projects/functions)
1072 error[E0308]: mismatched types
1073 --> src/main.rs:7:24
1074 |
1075 7 | fn plus_one(x: i32) -> i32 {
1076 | -------- ^^^ expected `i32`, found `()`
1077 | |
1078 | implicitly returns `()` as its body has no tail or `return` expression
1079 8 | x + 1;
1080 | - help: consider removing this semicolon
1081 ```
1082
1083 The main error message, “mismatched types,” reveals the core issue with this
1084 code. The definition of the function `plus_one` says that it will return an
1085 `i32`, but statements don’t evaluate to a value, which is expressed by `()`,
1086 the unit type. Therefore, nothing is returned, which contradicts the function
1087 definition and results in an error. In this output, Rust provides a message to
1088 possibly help rectify this issue: it suggests removing the semicolon, which
1089 would fix the error.
1090
1091 ## Comments
1092
1093 All programmers strive to make their code easy to understand, but sometimes
1094 extra explanation is warranted. In these cases, programmers leave *comments* in
1095 their source code that the compiler will ignore but people reading the source
1096 code may find useful.
1097
1098 Here’s a simple comment:
1099
1100 ```
1101 // hello, world
1102 ```
1103
1104 In Rust, the idiomatic comment style starts a comment with two slashes, and the
1105 comment continues until the end of the line. For comments that extend beyond a
1106 single line, you’ll need to include `//` on each line, like this:
1107
1108 ```
1109 // So we’re doing something complicated here, long enough that we need
1110 // multiple lines of comments to do it! Whew! Hopefully, this comment will
1111 // explain what’s going on.
1112 ```
1113
1114 Comments can also be placed at the end of lines containing code:
1115
1116 Filename: src/main.rs
1117
1118 ```
1119 fn main() {
1120 let lucky_number = 7; // I’m feeling lucky today
1121 }
1122 ```
1123
1124 But you’ll more often see them used in this format, with the comment on a
1125 separate line above the code it’s annotating:
1126
1127 Filename: src/main.rs
1128
1129 ```
1130 fn main() {
1131 // I’m feeling lucky today
1132 let lucky_number = 7;
1133 }
1134 ```
1135
1136 Rust also has another kind of comment, documentation comments, which we’ll
1137 discuss in the “Publishing a Crate to Crates.io” section of Chapter 14.
1138
1139 ## Control Flow
1140
1141 The ability to run some code depending on if a condition is true, or run some
1142 code repeatedly while a condition is true, are basic building blocks in most
1143 programming languages. The most common constructs that let you control the flow
1144 of execution of Rust code are `if` expressions and loops.
1145
1146 ### `if` Expressions
1147
1148 An `if` expression allows you to branch your code depending on conditions. You
1149 provide a condition and then state, “If this condition is met, run this block
1150 of code. If the condition is not met, do not run this block of code.”
1151
1152 Create a new project called *branches* in your *projects* directory to explore
1153 the `if` expression. In the *src/main.rs* file, input the following:
1154
1155 Filename: src/main.rs
1156
1157 ```
1158 fn main() {
1159 let number = 3;
1160
1161 if number < 5 {
1162 println!("condition was true");
1163 } else {
1164 println!("condition was false");
1165 }
1166 }
1167 ```
1168
1169 All `if` expressions start with the keyword `if`, followed by a condition. In
1170 this case, the condition checks whether or not the variable `number` has a
1171 value less than 5. We place block of code to execute if the condition is true
1172 immediately after the condition inside curly brackets. Blocks of code
1173 associated with the conditions in `if` expressions are sometimes called *arms*,
1174 just like the arms in `match` expressions that we discussed in the “Comparing
1175 the Guess to the Secret Number” section of Chapter 2.
1176
1177 Optionally, we can also include an `else` expression, which we chose
1178 to do here, to give the program an alternative block of code to execute should
1179 the condition evaluate to false. If you don’t provide an `else` expression and
1180 the condition is false, the program will just skip the `if` block and move on
1181 to the next bit of code.
1182
1183 Try running this code; you should see the following output:
1184
1185 ```
1186 $ cargo run
1187 Compiling branches v0.1.0 (file:///projects/branches)
1188 Finished dev [unoptimized + debuginfo] target(s) in 0.31s
1189 Running `target/debug/branches`
1190 condition was true
1191 ```
1192
1193 Let’s try changing the value of `number` to a value that makes the condition
1194 `false` to see what happens:
1195
1196 ```
1197 let number = 7;
1198 ```
1199
1200 Run the program again, and look at the output:
1201
1202 ```
1203 $ cargo run
1204 Compiling branches v0.1.0 (file:///projects/branches)
1205 Finished dev [unoptimized + debuginfo] target(s) in 0.31s
1206 Running `target/debug/branches`
1207 condition was false
1208 ```
1209
1210 It’s also worth noting that the condition in this code *must* be a `bool`. If
1211 the condition isn’t a `bool`, we’ll get an error. For example, try running the
1212 following code:
1213
1214 Filename: src/main.rs
1215
1216 ```
1217 fn main() {
1218 let number = 3;
1219
1220 if number {
1221 println!("number was three");
1222 }
1223 }
1224 ```
1225
1226 The `if` condition evaluates to a value of `3` this time, and Rust throws an
1227 error:
1228
1229 ```
1230 $ cargo run
1231 Compiling branches v0.1.0 (file:///projects/branches)
1232 error[E0308]: mismatched types
1233 --> src/main.rs:4:8
1234 |
1235 4 | if number {
1236 | ^^^^^^ expected `bool`, found integer
1237 ```
1238
1239 The error indicates that Rust expected a `bool` but got an integer. Unlike
1240 languages such as Ruby and JavaScript, Rust will not automatically try to
1241 convert non-Boolean types to a Boolean. You must be explicit and always provide
1242 `if` with a Boolean as its condition. If we want the `if` code block to run
1243 only when a number is not equal to `0`, for example, we can change the `if`
1244 expression to the following:
1245
1246 Filename: src/main.rs
1247
1248 ```
1249 fn main() {
1250 let number = 3;
1251
1252 if number != 0 {
1253 println!("number was something other than zero");
1254 }
1255 }
1256 ```
1257
1258 Running this code will print `number was something other than zero`.
1259
1260 #### Handling Multiple Conditions with `else if`
1261
1262 You can use multiple conditions by combining `if` and `else` in an `else if`
1263 expression. For example:
1264
1265 Filename: src/main.rs
1266
1267 ```
1268 fn main() {
1269 let number = 6;
1270
1271 if number % 4 == 0 {
1272 println!("number is divisible by 4");
1273 } else if number % 3 == 0 {
1274 println!("number is divisible by 3");
1275 } else if number % 2 == 0 {
1276 println!("number is divisible by 2");
1277 } else {
1278 println!("number is not divisible by 4, 3, or 2");
1279 }
1280 }
1281 ```
1282
1283 This program has four possible paths it can take. After running it, you should
1284 see the following output:
1285
1286 ```
1287 $ cargo run
1288 Compiling branches v0.1.0 (file:///projects/branches)
1289 Finished dev [unoptimized + debuginfo] target(s) in 0.31s
1290 Running `target/debug/branches`
1291 number is divisible by 3
1292 ```
1293
1294 When this program executes, it checks each `if` expression in turn and executes
1295 the first body for which the condition holds true. Note that even though 6 is
1296 divisible by 2, we don’t see the output `number is divisible by 2`, nor do we
1297 see the `number is not divisible by 4, 3, or 2` text from the `else` block.
1298 That’s because Rust only executes the block for the first true condition, and
1299 once it finds one, it doesn’t even check the rest.
1300
1301 Using too many `else if` expressions can clutter your code, so if you have more
1302 than one, you might want to refactor your code. Chapter 6 describes a powerful
1303 Rust branching construct called `match` for these cases.
1304
1305 #### Using `if` in a `let` Statement
1306
1307 Because `if` is an expression, we can use it on the right side of a `let`
1308 statement to assign the outcome to a variable, as in Listing 3-2.
1309
1310 Filename: src/main.rs
1311
1312 ```
1313 fn main() {
1314 let condition = true;
1315 let number = if condition { 5 } else { 6 };
1316
1317 println!("The value of number is: {}", number);
1318 }
1319 ```
1320
1321 Listing 3-2: Assigning the result of an `if` expression
1322 to a variable
1323
1324 The `number` variable will be bound to a value based on the outcome of the `if`
1325 expression. Run this code to see what happens:
1326
1327 ```
1328 $ cargo run
1329 Compiling branches v0.1.0 (file:///projects/branches)
1330 Finished dev [unoptimized + debuginfo] target(s) in 0.30s
1331 Running `target/debug/branches`
1332 The value of number is: 5
1333 ```
1334
1335 Remember that blocks of code evaluate to the last expression in them, and
1336 numbers by themselves are also expressions. In this case, the value of the
1337 whole `if` expression depends on which block of code executes. This means the
1338 values that have the potential to be results from each arm of the `if` must be
1339 the same type; in Listing 3-2, the results of both the `if` arm and the `else`
1340 arm were `i32` integers. If the types are mismatched, as in the following
1341 example, we’ll get an error:
1342
1343 Filename: src/main.rs
1344
1345 ```
1346 fn main() {
1347 let condition = true;
1348
1349 let number = if condition { 5 } else { "six" };
1350
1351 println!("The value of number is: {}", number);
1352 }
1353 ```
1354
1355 When we try to compile this code, we’ll get an error. The `if` and `else` arms
1356 have value types that are incompatible, and Rust indicates exactly where to
1357 find the problem in the program:
1358
1359 ```
1360 $ cargo run
1361 Compiling branches v0.1.0 (file:///projects/branches)
1362 error[E0308]: `if` and `else` have incompatible types
1363 --> src/main.rs:4:44
1364 |
1365 4 | let number = if condition { 5 } else { "six" };
1366 | - ^^^^^ expected integer, found `&str`
1367 | |
1368 | expected because of this
1369 ```
1370
1371 The expression in the `if` block evaluates to an integer, and the expression in
1372 the `else` block evaluates to a string. This won’t work because variables must
1373 have a single type, and Rust needs to know at compile time what type the
1374 `number` variable is, definitively. Knowing the type of `number` lets the
1375 compiler verify the type is valid everywhere we use `number`. Rust wouldn’t be
1376 able to do that if the type of `number` was only determined at runtime; the
1377 compiler would be more complex and would make fewer guarantees about the code
1378 if it had to keep track of multiple hypothetical types for any variable.
1379
1380 ### Repetition with Loops
1381
1382 It’s often useful to execute a block of code more than once. For this task,
1383 Rust provides several *loops*, which will run through the code inside the loop
1384 body to the end and then start immediately back at the beginning. To
1385 experiment with loops, let’s make a new project called *loops*.
1386
1387 Rust has three kinds of loops: `loop`, `while`, and `for`. Let’s try each one.
1388
1389 #### Repeating Code with `loop`
1390
1391 The `loop` keyword tells Rust to execute a block of code over and over again
1392 forever or until you explicitly tell it to stop.
1393
1394 As an example, change the *src/main.rs* file in your *loops* directory to look
1395 like this:
1396
1397 Filename: src/main.rs
1398
1399 ```
1400 fn main() {
1401 loop {
1402 println!("again!");
1403 }
1404 }
1405 ```
1406
1407 When we run this program, we’ll see `again!` printed over and over continuously
1408 until we stop the program manually. Most terminals support the keyboard shortcut
1409 <span class="keystroke">ctrl-c</span> to interrupt a program that is stuck in
1410 a continual loop. Give it a try:
1411
1412 ```
1413 $ cargo run
1414 Compiling loops v0.1.0 (file:///projects/loops)
1415 Finished dev [unoptimized + debuginfo] target(s) in 0.29s
1416 Running `target/debug/loops`
1417 again!
1418 again!
1419 again!
1420 again!
1421 ^Cagain!
1422 ```
1423
1424 The symbol `^C` represents where you pressed <span class="keystroke">ctrl-c
1425 </span>. You may or may not see the word `again!` printed after the `^C`,
1426 depending on where the code was in the loop when it received the interrupt
1427 signal.
1428
1429 Fortunately, Rust also provides a way to break out of a loop using code. You can
1430 place the `break` keyword within the loop to tell the program when to stop
1431 executing the loop. Recall that we did this in the guessing game in the
1432 “Quitting After a Correct Guess” section of Chapter 2 to exit the program when
1433 the user won the game by guessing the correct number.
1434
1435 We also used `continue` in the guessing game, which in a loop tells the program
1436 to skip over any remaining code in this iteration of the loop and go to the
1437 next iteration.
1438
1439 If you have loops within loops, `break` and `continue` apply to the innermost
1440 loop at that point. You can optionally specify a *loop label* on a loop that we
1441 can then use with `break` or `continue` to specify that those keywords apply to
1442 the labeled loop instead of the innermost loop. Here’s an example with two
1443 nested loops:
1444
1445 ```
1446 fn main() {
1447 let mut count = 0;
1448 'counting_up: loop {
1449 println!("count = {}", count);
1450 let mut remaining = 10;
1451
1452 loop {
1453 println!("remaining = {}", remaining);
1454 if remaining == 9 {
1455 break;
1456 }
1457 if count == 2 {
1458 break 'counting_up;
1459 }
1460 remaining -= 1;
1461 }
1462
1463 count += 1;
1464 }
1465 println!("End count = {}", count);
1466 }
1467 ```
1468
1469 The outer loop has the label `'counting_up`, and it will count up from 0 to 2.
1470 The inner loop without a label counts down from 10 to 9. The first `break` that
1471 doesn’t specify a label will exit the inner loop only. The `break
1472 'counting_up;` statement will exit the outer loop. This code prints:
1473
1474 ```
1475 Compiling loops v0.1.0 (file:///projects/loops)
1476 Finished dev [unoptimized + debuginfo] target(s) in 0.58s
1477 Running `target/debug/loops`
1478 count = 0
1479 remaining = 10
1480 remaining = 9
1481 count = 1
1482 remaining = 10
1483 remaining = 9
1484 count = 2
1485 remaining = 10
1486 End count = 2
1487 ```
1488
1489 #### Returning Values from Loops
1490
1491 One of the uses of a `loop` is to retry an operation you know might fail, such
1492 as checking whether a thread has completed its job. You might also need to pass
1493 the result of that operation out of the loop to the rest of your code. To do
1494 this, you can add the value you want returned after the `break` expression you
1495 use to stop the loop; that value will be returned out of the loop so you can
1496 use it, as shown here:
1497
1498 ```
1499 fn main() {
1500 let mut counter = 0;
1501
1502 let result = loop {
1503 counter += 1;
1504
1505 if counter == 10 {
1506 break counter * 2;
1507 }
1508 };
1509
1510 println!("The result is {}", result);
1511 }
1512 ```
1513
1514 Before the loop, we declare a variable named `counter` and initialize it to
1515 `0`. Then we declare a variable named `result` to hold the value returned from
1516 the loop. On every iteration of the loop, we add `1` to the `counter` variable,
1517 and then check whether the counter is equal to `10`. When it is, we use the
1518 `break` keyword with the value `counter * 2`. After the loop, we use a
1519 semicolon to end the statement that assigns the value to `result`. Finally, we
1520 print the value in `result`, which in this case is 20.
1521
1522 #### Conditional Loops with `while`
1523
1524 A program will often need to evaluate a condition within a loop. While the
1525 condition is true, the loop runs. When the condition ceases to be true, the
1526 program calls `break`, stopping the loop. It's possible to implement behavior
1527 like this using a combination of `loop`, `if`, `else`, and `break`; you could
1528 try that now in a program, if you’d like. However, this pattern is so common
1529 that Rust has a built-in language construct for it, called a `while` loop. In
1530 Listing 3-3, we use `while` to loop the program three times, counting down each
1531 time, and then, after the loop, print a message and exit.
1532
1533 Filename: src/main.rs
1534
1535 ```
1536 fn main() {
1537 let mut number = 3;
1538
1539 while number != 0 {
1540 println!("{}!", number);
1541
1542 number -= 1;
1543 }
1544
1545 println!("LIFTOFF!!!");
1546 }
1547 ```
1548
1549 Listing 3-3: Using a `while` loop to run code while a condition holds true
1550
1551 This construct eliminates a lot of nesting that would be necessary if you used
1552 `loop`, `if`, `else`, and `break`, and it’s clearer. While a condition holds
1553 true, the code runs; otherwise, it exits the loop.
1554
1555 #### Looping Through a Collection with `for`
1556
1557 You can choose to use the `while` construct to loop over the elements of a
1558 collection, such as an array. For example, the loop in Listing 3-4 prints each
1559 element in the array `a`.
1560
1561 Filename: src/main.rs
1562
1563 ```
1564 fn main() {
1565 let a = [10, 20, 30, 40, 50];
1566 let mut index = 0;
1567
1568 while index < 5 {
1569 println!("the value is: {}", a[index]);
1570
1571 index += 1;
1572 }
1573 }
1574 ```
1575
1576 Listing 3-4: Looping through each element of a collection using a `while` loop
1577
1578 Here, the code counts up through the elements in the array. It starts at index
1579 `0`, and then loops until it reaches the final index in the array (that is,
1580 when `index < 5` is no longer true). Running this code will print every element
1581 in the array:
1582
1583 ```
1584 $ cargo run
1585 Compiling loops v0.1.0 (file:///projects/loops)
1586 Finished dev [unoptimized + debuginfo] target(s) in 0.32s
1587 Running `target/debug/loops`
1588 the value is: 10
1589 the value is: 20
1590 the value is: 30
1591 the value is: 40
1592 the value is: 50
1593 ```
1594
1595 All five array values appear in the terminal, as expected. Even though `index`
1596 will reach a value of `5` at some point, the loop stops executing before trying
1597 to fetch a sixth value from the array.
1598
1599 However, this approach is error prone; we could cause the program to panic if
1600 the index value or test condition are incorrect. For example, if you changed
1601 the definition of the `a` array to have four elements but forgot to update the
1602 condition to `while index < 4`, the code would panic. It’s also slow, because
1603 the compiler adds runtime code to perform the conditional check of whether the
1604 index is within the bounds of the array on every iteration through the loop.
1605
1606 As a more concise alternative, you can use a `for` loop and execute some code
1607 for each item in a collection. A `for` loop looks like the code in Listing 3-5.
1608
1609 Filename: src/main.rs
1610
1611 ```
1612 fn main() {
1613 let a = [10, 20, 30, 40, 50];
1614
1615 for element in a {
1616 println!("the value is: {}", element);
1617 }
1618 }
1619 ```
1620
1621 Listing 3-5: Looping through each element of a collection using a `for` loop
1622
1623 When we run this code, we’ll see the same output as in Listing 3-4. More
1624 importantly, we’ve now increased the safety of the code and eliminated the
1625 chance of bugs that might result from going beyond the end of the array or not
1626 going far enough and missing some items.
1627
1628 Using the `for` loop, you wouldn’t need to remember to change any other code if
1629 you changed the number of values in the array, as you would with the method
1630 used in Listing 3-4.
1631
1632 The safety and conciseness of `for` loops make them the most commonly used loop
1633 construct in Rust. Even in situations in which you want to run some code a
1634 certain number of times, as in the countdown example that used a `while` loop
1635 in Listing 3-3, most Rustaceans would use a `for` loop. The way to do that
1636 would be to use a `Range`, provided by the standard library, which generates
1637 all numbers in sequence starting from one number and ending before another
1638 number.
1639
1640 Here’s what the countdown would look like using a `for` loop and another method
1641 we’ve not yet talked about, `rev`, to reverse the range:
1642
1643 Filename: src/main.rs
1644
1645 ```
1646 fn main() {
1647 for number in (1..4).rev() {
1648 println!("{}!", number);
1649 }
1650 println!("LIFTOFF!!!");
1651 }
1652 ```
1653
1654 This code is a bit nicer, isn’t it?
1655
1656 ## Summary
1657
1658 You made it! That was a sizable chapter: you learned about variables, scalar
1659 and compound data types, functions, comments, `if` expressions, and loops!
1660 To practice with the concepts discussed in this chapter, try building
1661 programs to do the following:
1662
1663 * Convert temperatures between Fahrenheit and Celsius.
1664 * Generate the nth Fibonacci number.
1665 * Print the lyrics to the Christmas carol “The Twelve Days of Christmas,”
1666 taking advantage of the repetition in the song.
1667
1668 When you’re ready to move on, we’ll talk about a concept in Rust that *doesn’t*
1669 commonly exist in other programming languages: ownership.