Variables
Like most other programming languages, Rust allows you to declare variables with a specific data type.
You use the let
keyword to indicate that you are declaring a new variable.
Variable Mutability
By default, variables in Rust are immutable, meaning that once they've been initialized, the values cannot be changed.
#![allow(unused)] fn main() { let name = "Trevor"; name = "Trevor"; // This is NOT allowed, and results in a compiler error. }
If you need to change the value of a variable, after it has been initialized, you can use the mut
keyword before the variable name.
#![allow(unused)] fn main() { let mut name = "Trevor"; name = "Joe"; }
These examples only show mutating values of a primitive data type.
For more complex data structures, using the mut
keyword may be necessary to allow alteration of the object's internal state.
Specify Data Type
When you declare a Rust variable, you can specify its data type, directly following the variable name.
For numeric types, you can specify the size of the type, such as u8
(unsigned 8-bit integer) or i128
(signed 128-bit integer).
Numeric Values
#![allow(unused)] fn main() { let age = 30u8; // Define an unsigned 8-bit integer let number_of_ducklings = 8u128; // Define an unsigned 128-bit integer (largest possible size) let cost: f32 = 30.28; // Define a 32-bit floating point value let cost: f64 = 80.99; // Define a 64-bit floating point value let item_price = 73.09f32; // Define a 32-bit floating point value let item_price = 91.12f64; // Define a 64-bit floating point value }
Variable Shadowing
Although some other languages don't allow you to re-declare the same variable, Rust does allow this.
We call this behavior variable "shadowing."
You can use the same variable name that has already been declared in the current scope
to declare a new variable with the let
keyword.
When the shadow variable goes out of scope, the variable reverts to its previous value.
Variable shadowing allows you to assign different data types to the same variable name (ie. &str
and u8
).
Here's a simple example on the Rust playground.
#[tokio::main] async fn main() { println!("How does Rust variable shadowing work?"); let person = "Trevor"; // Let's shadow the variable in a child block / scope { println!("The person variable is: {0}", person); // This shadowed variable goes out of scope // at the end of the block, and reverts to its previous value let person = 30u8; println!("Now we change person variable to: {0}", person); // Now we will nest another child block inside the parent block { let person = 1.18992152f32; println!("Now person has a floating point value: {0}", person); } // The f32 value goes out of scope here } // The u8 value goes out of scope here println!("Now we're back to: {0}", person); }
The output of this snippet should look similar to this:
How does Rust variable shadowing work?
The person variable is: Trevor
Now we change person variable to: 30
Now person has a floating point value: 1.1899215
Now we're back to: Trevor