Files
docs-rust/ch03/ch03-01-variables-and-mutability.html
2026-06-22 21:27:36 +05:30

207 lines
12 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Variables and Mutability</title>
</head>
<body>
<h2 id="variables-and-mutability"><a class="header" href="#variables-and-mutability">Variables and Mutability</a></h2>
<p>As mentioned in the <a href="../ch02/ch02-00-guessing-game-tutorial.html#storing-values-with-variables">“Storing Values with
Variables”</a><!-- ignore --> section, by default,
variables are immutable. This is one of many nudges Rust gives you to write
your code in a way that takes advantage of the safety and easy concurrency that
Rust offers. However, you still have the option to make your variables mutable.
Lets explore how and why Rust encourages you to favor immutability and why
sometimes you might want to opt out.</p>
<p>When a variable is immutable, once a value is bound to a name, you cant change
that value. To illustrate this, generate a new project called <em>variables</em> in
your <em>projects</em> directory by using <code>cargo new variables</code>.</p>
<p>Then, in your new <em>variables</em> directory, open <em>src/main.rs</em> and replace its
code with the following code, which wont compile just yet:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><code class="language-rust ignore does_not_compile">fn main() {
let x = 5;
println!("The value of x is: {x}");
x = 6;
println!("The value of x is: {x}");
}</code></pre>
<p>Save and run the program using <code>cargo run</code>. You should receive an error message
regarding an immutability error, as shown in this output:</p>
<pre><code class="language-console">$ cargo run
Compiling variables v0.1.0 (file:///projects/variables)
error[E0384]: cannot assign twice to immutable variable `x`
--&gt; src/main.rs:4:5
|
2 | let x = 5;
| - first assignment to `x`
3 | println!("The value of x is: {x}");
4 | x = 6;
| ^^^^^ cannot assign twice to immutable variable
|
help: consider making this binding mutable
|
2 | let mut x = 5;
| +++
For more information about this error, try `rustc --explain E0384`.
error: could not compile `variables` (bin "variables") due to 1 previous error
</code></pre>
<p>This example shows how the compiler helps you find errors in your programs.
Compiler errors can be frustrating, but really they only mean your program
isnt safely doing what you want it to do yet; they do <em>not</em> mean that youre
not a good programmer! Experienced Rustaceans still get compiler errors.</p>
<p>You received the error message <code>cannot assign twice to immutable variable `x`</code> because you tried to assign a second value to the immutable <code>x</code> variable.</p>
<p>Its important that we get compile-time errors when we attempt to change a
value thats designated as immutable, because this very situation can lead to
bugs. If one part of our code operates on the assumption that a value will
never change and another part of our code changes that value, its possible
that the first part of the code wont do what it was designed to do. The cause
of this kind of bug can be difficult to track down after the fact, especially
when the second piece of code changes the value only <em>sometimes</em>. The Rust
compiler guarantees that when you state that a value wont change, it really
wont change, so you dont have to keep track of it yourself. Your code is thus
easier to reason through.</p>
<p>But mutability can be very useful and can make code more convenient to write.
Although variables are immutable by default, you can make them mutable by
adding <code>mut</code> in front of the variable name as you did in <a href="../ch02/ch02-00-guessing-game-tutorial.html#storing-values-with-variables">Chapter
2</a><!-- ignore -->. Adding <code>mut</code> also conveys
intent to future readers of the code by indicating that other parts of the code
will be changing this variables value.</p>
<p>For example, lets change <em>src/main.rs</em> to the following:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre class="playground"><code class="language-rust edition2024">fn main() {
let mut x = 5;
println!("The value of x is: {x}");
x = 6;
println!("The value of x is: {x}");
}</code></pre>
<p>When we run the program now, we get this:</p>
<pre><code class="language-console">$ cargo run
Compiling variables v0.1.0 (file:///projects/variables)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.30s
Running `target/debug/variables`
The value of x is: 5
The value of x is: 6
</code></pre>
<p>Were allowed to change the value bound to <code>x</code> from <code>5</code> to <code>6</code> when <code>mut</code> is
used. Ultimately, deciding whether to use mutability or not is up to you and
depends on what you think is clearest in that particular situation.</p>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="constants"></a></p>
<h3 id="declaring-constants"><a class="header" href="#declaring-constants">Declaring Constants</a></h3>
<p>Like immutable variables, <em>constants</em> are values that are bound to a name and
are not allowed to change, but there are a few differences between constants
and variables.</p>
<p>First, you arent allowed to use <code>mut</code> with constants. Constants arent just
immutable by default—theyre always immutable. You declare constants using the
<code>const</code> keyword instead of the <code>let</code> keyword, and the type of the value <em>must</em>
be annotated. Well cover types and type annotations in the next section,
<a href="ch03-02-data-types.html#data-types">“Data Types”</a><!-- ignore -->, so dont worry about the details
right now. Just know that you must always annotate the type.</p>
<p>Constants can be declared in any scope, including the global scope, which makes
them useful for values that many parts of code need to know about.</p>
<p>The last difference is that constants may be set only to a constant expression,
not the result of a value that could only be computed at runtime.</p>
<p>Heres an example of a constant declaration:</p>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;
<span class="boring">}</span></code></pre>
<p>The constants name is <code>THREE_HOURS_IN_SECONDS</code>, and its value is set to the
result of multiplying 60 (the number of seconds in a minute) by 60 (the number
of minutes in an hour) by 3 (the number of hours we want to count in this
program). Rusts naming convention for constants is to use all uppercase with
underscores between words. The compiler is able to evaluate a limited set of
operations at compile time, which lets us choose to write out this value in a
way thats easier to understand and verify, rather than setting this constant
to the value 10,800. See the <a href="../reference/const_eval.html">Rust References section on constant
evaluation</a> for more information on what operations can be used
when declaring constants.</p>
<p>Constants are valid for the entire time a program runs, within the scope in
which they were declared. This property makes constants useful for values in
your application domain that multiple parts of the program might need to know
about, such as the maximum number of points any player of a game is allowed to
earn, or the speed of light.</p>
<p>Naming hardcoded values used throughout your program as constants is useful in
conveying the meaning of that value to future maintainers of the code. It also
helps to have only one place in your code that you would need to change if the
hardcoded value needed to be updated in the future.</p>
<h3 id="shadowing"><a class="header" href="#shadowing">Shadowing</a></h3>
<p>As you saw in the guessing game tutorial in <a href="../ch02/ch02-00-guessing-game-tutorial.html#comparing-the-guess-to-the-secret-number">Chapter
2</a><!-- ignore -->, you can declare a
new variable with the same name as a previous variable. Rustaceans say that the
first variable is <em>shadowed</em> by the second, which means that the second
variable is what the compiler will see when you use the name of the variable.
In effect, the second variable overshadows the first, taking any uses of the
variable name to itself until either it itself is shadowed or the scope ends.
We can shadow a variable by using the same variables name and repeating the
use of the <code>let</code> keyword as follows:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre class="playground"><code class="language-rust edition2024">fn main() {
let x = 5;
let x = x + 1;
{
let x = x * 2;
println!("The value of x in the inner scope is: {x}");
}
println!("The value of x is: {x}");
}</code></pre>
<p>This program first binds <code>x</code> to a value of <code>5</code>. Then, it creates a new variable
<code>x</code> by repeating <code>let x =</code>, taking the original value and adding <code>1</code> so that
the value of <code>x</code> is <code>6</code>. Then, within an inner scope created with the curly
brackets, the third <code>let</code> statement also shadows <code>x</code> and creates a new
variable, multiplying the previous value by <code>2</code> to give <code>x</code> a value of <code>12</code>.
When that scope is over, the inner shadowing ends and <code>x</code> returns to being <code>6</code>.
When we run this program, it will output the following:</p>
<pre><code class="language-console">$ cargo run
Compiling variables v0.1.0 (file:///projects/variables)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.31s
Running `target/debug/variables`
The value of x in the inner scope is: 12
The value of x is: 6
</code></pre>
<p>Shadowing is different from marking a variable as <code>mut</code> because well get a
compile-time error if we accidentally try to reassign to this variable without
using the <code>let</code> keyword. By using <code>let</code>, we can perform a few transformations
on a value but have the variable be immutable after those transformations have
completed.</p>
<p>The other difference between <code>mut</code> and shadowing is that because were
effectively creating a new variable when we use the <code>let</code> keyword again, we can
change the type of the value but reuse the same name. For example, say our
program asks a user to show how many spaces they want between some text by
inputting space characters, and then we want to store that input as a number:</p>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span> let spaces = " ";
let spaces = spaces.len();
<span class="boring">}</span></code></pre>
<p>The first <code>spaces</code> variable is a string type, and the second <code>spaces</code> variable
is a number type. Shadowing thus spares us from having to come up with
different names, such as <code>spaces_str</code> and <code>spaces_num</code>; instead, we can reuse
the simpler <code>spaces</code> name. However, if we try to use <code>mut</code> for this, as shown
here, well get a compile-time error:</p>
<pre><code class="language-rust ignore does_not_compile"><span class="boring">fn main() {
</span> let mut spaces = " ";
spaces = spaces.len();
<span class="boring">}</span></code></pre>
<p>The error says were not allowed to mutate a variables type:</p>
<pre><code class="language-console">$ cargo run
Compiling variables v0.1.0 (file:///projects/variables)
error[E0308]: mismatched types
--&gt; src/main.rs:3:14
|
2 | let mut spaces = " ";
| ----- expected due to this value
3 | spaces = spaces.len();
| ^^^^^^^^^^^^ expected `&amp;str`, found `usize`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `variables` (bin "variables") due to 1 previous error
</code></pre>
<p>Now that weve explored how variables work, lets look at more data types they
can have.</p>
</body>
</html>