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