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