]>
Commit | Line | Data |
---|---|---|
13cf67c4 XL |
1 | ## Variables and Mutability |
2 | ||
3 | As mentioned in Chapter 2, by default variables are immutable. This is one of | |
4 | many nudges Rust gives you to write your code in a way that takes advantage of | |
5 | the safety and easy concurrency that Rust offers. However, you still have the | |
6 | option to make your variables mutable. Let’s explore how and why Rust | |
7 | encourages you to favor immutability and why sometimes you might want to opt | |
8 | out. | |
9 | ||
10 | When a variable is immutable, once a value is bound to a name, you can’t change | |
11 | that value. To illustrate this, let’s generate a new project called *variables* | |
12 | in your *projects* directory by using `cargo new variables`. | |
13 | ||
14 | Then, in your new *variables* directory, open *src/main.rs* and replace its | |
15 | code with the following code that won’t compile just yet: | |
16 | ||
17 | <span class="filename">Filename: src/main.rs</span> | |
18 | ||
19 | ```rust,ignore,does_not_compile | |
74b04a01 | 20 | {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/src/main.rs}} |
13cf67c4 XL |
21 | ``` |
22 | ||
23 | Save and run the program using `cargo run`. You should receive an error | |
24 | message, as shown in this output: | |
25 | ||
f035d41b | 26 | ```console |
74b04a01 | 27 | {{#include ../listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt}} |
13cf67c4 XL |
28 | ``` |
29 | ||
30 | This example shows how the compiler helps you find errors in your programs. | |
31 | Even though compiler errors can be frustrating, they only mean your program | |
32 | isn’t safely doing what you want it to do yet; they do *not* mean that you’re | |
33 | not a good programmer! Experienced Rustaceans still get compiler errors. | |
34 | ||
69743fb6 XL |
35 | The error message indicates that the cause of the error is that you `cannot |
36 | assign twice to immutable variable x`, because you tried to assign a second | |
37 | value to the immutable `x` variable. | |
13cf67c4 XL |
38 | |
39 | It’s important that we get compile-time errors when we attempt to change a | |
40 | value that we previously designated as immutable because this very situation | |
41 | can lead to bugs. If one part of our code operates on the assumption that a | |
42 | value will never change and another part of our code changes that value, it’s | |
43 | possible that the first part of the code won’t do what it was designed to do. | |
44 | The cause of this kind of bug can be difficult to track down after the fact, | |
45 | especially when the second piece of code changes the value only *sometimes*. | |
46 | ||
47 | In Rust, the compiler guarantees that when you state that a value won’t change, | |
48 | it really won’t change. That means that when you’re reading and writing code, | |
49 | you don’t have to keep track of how and where a value might change. Your code | |
50 | is thus easier to reason through. | |
51 | ||
52 | But mutability can be very useful. Variables are immutable only by default; as | |
53 | you did in Chapter 2, you can make them mutable by adding `mut` in front of the | |
54 | variable name. In addition to allowing this value to change, `mut` conveys | |
55 | intent to future readers of the code by indicating that other parts of the code | |
e74abb32 | 56 | will be changing this variable’s value. |
13cf67c4 XL |
57 | |
58 | For example, let’s change *src/main.rs* to the following: | |
59 | ||
60 | <span class="filename">Filename: src/main.rs</span> | |
61 | ||
62 | ```rust | |
74b04a01 | 63 | {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-02-adding-mut/src/main.rs}} |
13cf67c4 XL |
64 | ``` |
65 | ||
66 | When we run the program now, we get this: | |
67 | ||
f035d41b | 68 | ```console |
74b04a01 | 69 | {{#include ../listings/ch03-common-programming-concepts/no-listing-02-adding-mut/output.txt}} |
13cf67c4 XL |
70 | ``` |
71 | ||
72 | We’re allowed to change the value that `x` binds to from `5` to `6` when `mut` | |
73 | is used. In some cases, you’ll want to make a variable mutable because it makes | |
74 | the code more convenient to write than if it had only immutable variables. | |
75 | ||
76 | There are multiple trade-offs to consider in addition to the prevention of | |
77 | bugs. For example, in cases where you’re using large data structures, mutating | |
78 | an instance in place may be faster than copying and returning newly allocated | |
79 | instances. With smaller data structures, creating new instances and writing in | |
80 | a more functional programming style may be easier to think through, so lower | |
81 | performance might be a worthwhile penalty for gaining that clarity. | |
82 | ||
83 | ### Differences Between Variables and Constants | |
84 | ||
85 | Being unable to change the value of a variable might have reminded you of | |
86 | another programming concept that most other languages have: *constants*. Like | |
87 | immutable variables, constants are values that are bound to a name and are not | |
88 | allowed to change, but there are a few differences between constants and | |
89 | variables. | |
90 | ||
91 | First, you aren’t allowed to use `mut` with constants. Constants aren’t just | |
92 | immutable by default—they’re always immutable. | |
93 | ||
94 | You declare constants using the `const` keyword instead of the `let` keyword, | |
95 | and the type of the value *must* be annotated. We’re about to cover types and | |
9fa01778 XL |
96 | type annotations in the next section, [“Data Types,”][data-types]<!-- ignore |
97 | --> so don’t worry about the details right now. Just know that you must always | |
98 | annotate the type. | |
13cf67c4 XL |
99 | |
100 | Constants can be declared in any scope, including the global scope, which makes | |
101 | them useful for values that many parts of code need to know about. | |
102 | ||
103 | The last difference is that constants may be set only to a constant expression, | |
104 | not the result of a function call or any other value that could only be | |
105 | computed at runtime. | |
106 | ||
107 | Here’s an example of a constant declaration where the constant’s name is | |
69743fb6 XL |
108 | `MAX_POINTS` and its value is set to 100,000. (Rust’s naming convention for |
109 | constants is to use all uppercase with underscores between words, and | |
110 | underscores can be inserted in numeric literals to improve readability): | |
13cf67c4 XL |
111 | |
112 | ```rust | |
113 | const MAX_POINTS: u32 = 100_000; | |
114 | ``` | |
115 | ||
116 | Constants are valid for the entire time a program runs, within the scope they | |
117 | were declared in, making them a useful choice for values in your application | |
118 | domain that multiple parts of the program might need to know about, such as the | |
119 | maximum number of points any player of a game is allowed to earn or the speed | |
120 | of light. | |
121 | ||
122 | Naming hardcoded values used throughout your program as constants is useful in | |
123 | conveying the meaning of that value to future maintainers of the code. It also | |
124 | helps to have only one place in your code you would need to change if the | |
125 | hardcoded value needed to be updated in the future. | |
126 | ||
127 | ### Shadowing | |
128 | ||
9fa01778 XL |
129 | As you saw in the guessing game tutorial in the [“Comparing the Guess to the |
130 | Secret Number”][comparing-the-guess-to-the-secret-number]<!-- ignore --> | |
131 | section in Chapter 2, you can declare a new variable with the same name as a | |
6a06907d XL |
132 | previous variable. Rustaceans say that the first variable is *shadowed* by the |
133 | second, which means that the second variable’s value is what appears when the | |
134 | variable is used. We can shadow a variable by using the same variable’s name | |
135 | and repeating the use of the `let` keyword as follows: | |
13cf67c4 XL |
136 | |
137 | <span class="filename">Filename: src/main.rs</span> | |
138 | ||
139 | ```rust | |
74b04a01 | 140 | {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-03-shadowing/src/main.rs}} |
13cf67c4 XL |
141 | ``` |
142 | ||
143 | This program first binds `x` to a value of `5`. Then it shadows `x` by | |
144 | repeating `let x =`, taking the original value and adding `1` so the value of | |
145 | `x` is then `6`. The third `let` statement also shadows `x`, multiplying the | |
146 | previous value by `2` to give `x` a final value of `12`. When we run this | |
147 | program, it will output the following: | |
148 | ||
f035d41b | 149 | ```console |
74b04a01 | 150 | {{#include ../listings/ch03-common-programming-concepts/no-listing-03-shadowing/output.txt}} |
13cf67c4 XL |
151 | ``` |
152 | ||
532ac7d7 | 153 | Shadowing is different from marking a variable as `mut`, because we’ll get a |
13cf67c4 XL |
154 | compile-time error if we accidentally try to reassign to this variable without |
155 | using the `let` keyword. By using `let`, we can perform a few transformations | |
156 | on a value but have the variable be immutable after those transformations have | |
157 | been completed. | |
158 | ||
159 | The other difference between `mut` and shadowing is that because we’re | |
160 | effectively creating a new variable when we use the `let` keyword again, we can | |
161 | change the type of the value but reuse the same name. For example, say our | |
162 | program asks a user to show how many spaces they want between some text by | |
163 | inputting space characters, but we really want to store that input as a number: | |
164 | ||
165 | ```rust | |
74b04a01 | 166 | {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-04-shadowing-can-change-types/src/main.rs:here}} |
13cf67c4 XL |
167 | ``` |
168 | ||
169 | This construct is allowed because the first `spaces` variable is a string type | |
170 | and the second `spaces` variable, which is a brand-new variable that happens to | |
171 | have the same name as the first one, is a number type. Shadowing thus spares us | |
172 | from having to come up with different names, such as `spaces_str` and | |
173 | `spaces_num`; instead, we can reuse the simpler `spaces` name. However, if we | |
174 | try to use `mut` for this, as shown here, we’ll get a compile-time error: | |
175 | ||
176 | ```rust,ignore,does_not_compile | |
74b04a01 | 177 | {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/src/main.rs:here}} |
13cf67c4 XL |
178 | ``` |
179 | ||
180 | The error says we’re not allowed to mutate a variable’s type: | |
181 | ||
f035d41b | 182 | ```console |
74b04a01 | 183 | {{#include ../listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/output.txt}} |
13cf67c4 XL |
184 | ``` |
185 | ||
186 | Now that we’ve explored how variables work, let’s look at more data types they | |
187 | can have. | |
9fa01778 XL |
188 | |
189 | [comparing-the-guess-to-the-secret-number]: | |
190 | ch02-00-guessing-game-tutorial.html#comparing-the-guess-to-the-secret-number | |
191 | [data-types]: ch03-02-data-types.html#data-types |