This article will help you learn variables in rust via simple examples.
[lwptoc]
What is an immutable variable in Rust?
It's a variable whose VALUE once bound to a name, can’t change.
What's it's advantage?
Immutable vraibles provide the advantage of the safety and easy concurrency.
Immutability example
Type the following code:
main.rs:
fn main() {
let x = 5;
println!("The value of x is: {}", x);
x = 6;
println!("The value of x is: {}", x);
}
Try to run it using cargo run
.
$ cargo run
You will see the following error:
Compiling variables v0.1.0 (file:///projects/variables)
error[E0384]: cannot assign twice to immutable variable x
--> src/main.rs:4:5
|
2 | let x = 5;
| -
| |
| first assignment to x
| help: make this binding mutable: mut x
3 | println!("The value of x is: {}", x);
4 | x = 6;
| ^^^^^ cannot assign twice to immutable variable
error: aborting due to previous error
The error message indicates that the cause of the error is that you cannot assign twice to immutable variable x, because you tried to assign a second value to the immutable x variable.
Can a Rust variable be mutable?
Yes. Rust variables can be made mutable.Mutability can be very useful at times. Variables are immutable only by default,but you can make them mutable by adding mut
in front of the variable name.
What does Making a variable mutable imply?
It results tothe following:
- It allows the value of the variable to change.
-
mut
also conveys intent to future readers of the code by indicating that other parts of the code will be changing this variable’s value.
Can you give an example of a mutable variable?
Yeah. Here's an example of a mutable variable in rust:
fn main() {
let mut x = 5;
println!("The value of x is: {}", x);
x = 6;
println!("The value of x is: {}", x);
}
If you run it you will get the following:
$ cargo run
Compiling variables v0.1.0 (file:///projects/variables)
Finished dev [unoptimized + debuginfo] target(s) in 0.30s
Running target/debug/variables
The value of x is: 5
The value of x is: 6
We’re allowed to change the value that x binds to from 5 to 6 when mut is used.
What are trade-offs to consider when using mutable variables
- Bug prevention.
- In cases where you’re using large data structures, mutating an instance in place may be faster than copying and returning newly allocated instances.
- With smaller data structures, creating new instances and writing in a more functional programming style may be easier to think through, so lower performance might be a worthwhile penalty for gaining that clarity.
What are differences and similarities between constants and immutable variables in rust
Here are the similarities:
- You cannot change the value of a variable in both a constant and immutable variable. In both values are bound to a name and are not allowed to change.
Here are the differences however:
- You aren’t allowed to use
mut
with constants. Constants aren’t just immutable by default—they’re always immutable. - You declare constants using the const keyword instead of the
let
keyword. - The type of the value must be annotated in constants.
- 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.
- The last difference is that constants may be set only to a constant expression, not the result of a function call or any other value that could only be computed at runtime.
Here is a coonstant declaration:
#![allow(unused)]
fn main() {
const MAX_POINTS: u32 = 100_000;
}
What is Variable Shadowing in rust?
In rust you can declare a new variable with the same name as a previous variable. In that case we say that the first variable is shadowed by the second, which means that the second variable’s value is what appears when the variable is used. We can shadow a variable by using the same variable’s name and repeating the use of the let keyword as follows:
fn main() {
let x = 5;
let x = x + 1;
let x = x * 2;
println!("The value of x is: {}", x);
}
Then run it:
$ cargo run
If you run it you get the following:
Compiling variables v0.1.0 (file:///projects/variables)
Finished dev [unoptimized + debuginfo] target(s) in 0.31s
Running target/debug/variables
The value of x is: 12
What is the difference between shadowing a varaible and making it mutable?
They are different in the following ways:
- In shadowing we’ll get a compile-time error if we accidentally try to reassign to this variable without using the
let
keyword. By usinglet
, we can perform a few transformations on a value but have the variable be immutable after those transformations have been completed. - The other difference between mut and shadowing is that because we’re effectively creating a new variable when we use the let keyword again, we can change the type of the value but reuse the same name.
More Examples
Simple Mutability Example
main.rs:
const MAX_POINTS: u32 = 100_000; // constant declaration at
// the global level.
const MAX_FLOATS: f32 = 285_351.95; // NOTE: With f32 -> The amount of max floats is: 285351.94
const MAX_FLOAT: f64 = 285_351.95; // NOTE: With f64 -> The amount of max float is: 285351.95
// Correct size of the dataype makes a difference.
fn main() {
let mut x = 5;
println!("The value of x is: {}", x);
x = 6; // This is an error and the program
// cannot run without first mutating the
// value of x.
println!("The value of x is: {}", x);
println!("The amount of max points is: {}", MAX_POINTS); // The amount of max points is: 100000
println!("The amount of max floats is: {}", MAX_FLOATS); // The amount of max floats is: 285351.94
println!("The amount of max float is: {}", MAX_FLOAT); // The amount of max floats is: 285351.95
let x = 5;
let x = x + 1; // The program initially binds x to a value of 5 but then
// shadows it by repeating let x which takes the original
// value and add's 1.
let x = x * 2;
println!("The value of x is: {}", x); // The value of x is: 12
let spaces = " ";
let spaces = spaces.len();
println!("The number of spaces is: {}", spaces); // The number of spaces is: 4
}
If you run it you get:
The value of x is: 5
The value of x is: 6
The amount of max points is: 100000
The amount of max floats is: 285351.94
The amount of max float is: 285351.95
The value of x is: 12
The number of spaces is: 4
Example 2
Practising Mutability, Creation and shadowing:
fn main() {
let mut x = 5;
println!("The value of x is {}", x);
x = 6;
println!("The value of x is {}", x);
let y = 5;
let y = y + 5;
let y = y * 2;
println!("The value of y is {}", y)
}
If you run it you get the following:
The value of x is 5
The value of x is 6
The value of y is 20
Example 3
Showcasing mutability using a simple example:
fn main() {
let mut temperature = 30;
println!("{}", temperature);
temperature = 32;
println!("{}", temperature);
}
If you run it you get:
30
32
Example 4: Simple Variables Example
Learn Variables using this simple example.
Step 1: Create Project
- Open your
Rust
IDE. - In the menu go to
File --> Create New Project
.
Step 2: Add Dependencies
Go to your Cargo.toml
and modify it as follows:
[package]
name = "variables"
version = "0.1.0"
authors = ["Inanc Gumus <[email protected]>"]
edition = "2018"
[dependencies]
Step 3: Write Code
Next create a file known as main.rs
and add the following code:
fn main() {
let x = 5;
println!("x: {}", x);
// x variable is immutable.
// so we can't change its value.
// x = 6;
// but we can declare a new variable,
// with the same name: x
.
//
// this way, we don't need to imagine
// new variable names.
let x = 6;
println!("x: {}", x);
// we can also create a constant.
// constant are compile-time values.
// so, anywhere MAX_VALUE appears, the
// compiler will change it with 10 instead.
//
// instead of using hardcoded values, use
// constants instead.
const MAX_VALUE: u32 = 10;
println!("MAX_VALUE: {}", MAX_VALUE);
// SHADOWING
let spaces = " "; // &str
let spaces = spaces.len(); // usize
println!("spaces: {}", spaces);
}
Here is the full code:
main.rs
fn main() {
let x = 5;
println!("x: {}", x);
// x variable is immutable.
// so we can't change its value.
// x = 6;
// but we can declare a new variable,
// with the same name: x
.
//
// this way, we don't need to imagine
// new variable names.
let x = 6;
println!("x: {}", x);
// we can also create a constant.
// constant are compile-time values.
// so, anywhere MAX_VALUE appears, the
// compiler will change it with 10 instead.
//
// instead of using hardcoded values, use
// constants instead.
const MAX_VALUE: u32 = 10;
println!("MAX_VALUE: {}", MAX_VALUE);
// SHADOWING
let spaces = " "; // &str
let spaces = spaces.len(); // usize
println!("spaces: {}", spaces);
}
Run
Copy the code, build and run.
Reference
Here are the reference links:
Number | Link |
---|---|
1. | Download Example |
2. | Follow code author |
3. | Code: Apache 2.0 License |