This article will use simple metaphors and clear logic to help you deeply understand the core concepts behind Rust variables, enabling you not only to “use them” but also to “understand why”.
Rust’s “Box Philosophy”: Variables, Mutability, Constants, and Hiding
Imagine that variables in Rust are like individual boxes. You put values (like numbers or text) into the boxes and label them (variable names), so you can find what’s inside the box later by the label. However, Rust manages these boxes very strictly, which is the core of its safety and efficiency. Let’s take a look at Rust’s “box management rules”.
Rule 1: Boxes are Locked by Default (Immutability)
In the world of Rust, when you create a box, it is locked by default, meaning that once you put something inside, you cannot change it! This may sound a bit “rigid”? But actually, it’s very clever!
Why is being locked a good thing?
Imagine you and a friend start a company, and you agree that “the registered capital of the company is 1 million.” If this number can be changed at will, it would cause big problems! Today it changes to 2 million, tomorrow to 500,000, and the accounts would be a mess.
The same goes for programming. If a value (like “maximum number of players”) is marked as immutable, other parts of the program can safely assume it won’t change. This avoids hard-to-trace bugs like “I thought it was 100, but you secretly changed it to 200”.
Try this:
–javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
fn main() {
let x = 5; // Create a box named x, put the number 5 inside, and lock it.
println!("x's value is: {x}");
x = 6; // Trying to put 6 inside? No way! The box is locked!
println!("x's value is: {x}");
}
Running this code, the Rust compiler will immediately shout: “Error! You cannot reassign a locked box (immutable variable <strong><span>x</span></strong>)!” It will even kindly tell you: “Hey, if you really want it to be mutable, try adding a <span>mut</span>!”
Rule 2: Want to Change? Please “Unlock” First (Mutability <span>mut</span>)
If you really need a box that can be modified at any time, Rust allows you to “unlock” it, but you must explicitly request it. The way to do this is by using the <span>mut</span> keyword.
–javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
fn main() {
let mut x = 5; // Create a box named x, put 5 inside, but this time it's "unlockable"!
println!("x's value is: {x}");
x = 6; // Now it's okay! Change 5 to 6.
println!("x's value is: {x}");
}
<strong><span>mut</span></strong>‘s deeper meaning:
-
1.
Safety: Forces you to think “Does this value really need to change?” In most cases, values do not need to change, and being locked is safer.
-
2.
Communication:
<span>mut</span>is like a prominent label, telling other programmers (including your future self): “Attention! The value of this<span>x</span>may be modified later in the code!” This makes the code easier to understand and maintain.
Core Idea: Immutable by default, use <span>mut</span> only when necessary. This is the cornerstone of Rust’s safety.
Rule 3: The Unchanging “Golden Box” (Constant <span>const</span>)
Sometimes, you have values that are “ironclad rules” that absolutely, positively cannot change, such as “There are 3600 seconds in an hour.” For such values, Rust has a more advanced “golden box”—constants.
–javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
const SECONDS_IN_HOUR: u32 = 60 * 60;
Constants vs Ordinary Variables:
|
Feature |
Ordinary Variable ( |
Constant ( |
|---|---|---|
|
Mutability |
Default is immutable, can be made mutable with |
Always immutable, cannot add |
|
Declaration Location |
Usually inside functions |
Can be declared anywhere, including globally (accessible throughout the program) |
|
Value Source |
Can be the result of runtime calculations (like user input) |
Can only be values that can be computed at compile time (constant expressions) |
|
Naming Convention |
|
|
Why can constants only be compile-time values?
Because constants are determined before the program starts. They cannot depend on things that can only be known at runtime, such as user input or the results of network requests.<span>60 * 60</span> can be calculated at compile time to be 3600, so it’s fine.
Core Idea: Constants are the “hard-coded rules” of the program, safe, efficient, and with a wide scope.
Rule 4: The “Transformation” of Boxes (Shadowing <span>Shadowing</span>)
This is a very cool feature of Rust! Imagine you have a box called <span>spaces</span> that contains a string of spaces <span>" "</span>. Now, you don’t want to know the spaces themselves, but want to know how long they are (3 characters). You don’t want to create a new name (like <span>spaces_length</span>), what do you do?
Rust allows you to redeclare a new box with the same name, which will “hide” (shadow) the old box. The old box still exists, but you can no longer “see” it; you can only see the new one.
–javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
fn main() {
let spaces = " "; // The first spaces box, containing the string " "
let spaces = spaces.len(); // Transform! Use a new box with the same name, containing the length of the old box, which is 3
println!("spaces's value is: {spaces}"); // Prints out 3
}
Hiding vs <strong><span>mut</span></strong>: Key Differences!
-
1.
Changing Types:
–javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
fn main() { let mut spaces = " "; // spaces is a string type spaces = spaces.len(); // Error! You cannot put a number into a box declared as a string! }
-
•
Hiding: Possible! The first
<span>spaces</span>is a<span>string</span>, and the second<span>spaces</span>is a<span>number</span>. The type has changed! -
•
<strong><span>mut</span></strong>: Not allowed! Once the box type is determined (for example,<span>let mut x = 5;</span>is<span>i32</span>), it cannot be changed to another type.
2.
Safety:
-
•
Hiding: Each time, a completely new box is created. The old box is hidden but will not be accidentally modified.
-
•
<strong><span>mut</span></strong>: It is the same box, and the value inside is directly modified. If multiple pieces of code<span>mut</span>the same variable, it can lead to errors.
3.
Resetting Mutability:
-
•
Hiding: You can “first
<span>mut</span>and then hide as immutable”. For example, first create a<span>mut</span>box for a series of calculations, and finally hide it with<span>let</span>to make it immutable, ensuring safety in subsequent code.
Core Idea: Hiding is “creating a new identity”, while <span>mut</span> is “modifying the old identity”. Hiding is more flexible (can change types) and can return to an immutable safe state after the transformation.
Summary: The Four Treasures of Rust Variables
Through these four rules, Rust has built a powerful memory and data management mechanism:
-
1.
<strong><span>let</span></strong>(Immutable): Default safety. The box is locked to prevent accidental modification. -
2.
<strong><span>let mut</span></strong>(Mutable): Explicit authorization. Unlock only when modification is needed, and clearly inform others. -
3.
<strong><span>const</span></strong>(Constant): Global ironclad rules. Determined at compile time, never changes, with a wide scope. -
4.
<strong><span>let</span></strong>(Hiding): Flexible transformation. Same name for a new box, can change types, and return to safety after transformation.
These rules work together to allow Rust programs to catch a large number of potential errors (such as data races, null pointers, type errors) at compile time without sacrificing runtime performance. This is the essence of Rust’s “zero-cost abstractions” and “memory safety”.
Now, you have understood the core philosophy behind Rust variables.
Remember: Rust does not restrict you, but helps you write more reliable and efficient code through strict rules. Keep exploring!