Introduction
Rust is a programming language that is well known for its type-safety and performance. Variables and data types are integral parts of all programming languages, hence, understanding variables and data types is essential for any Rust developer. This article explores how Rust handles variable declarations, immutability, control flow, and the variety of built-in data types, providing a solid foundation for building efficient programs.
What are Rust Variables?
Variables are named storage locations in a computer memory; they hold values that are used for the overall functioning of computer programs. The value that a variable hold can be a number, strings of text, or other complex data.
Variables in Rust are immutable by default, meaning that you cannot change the value of a declared variable at a later time, even you cannot mistakenly change the value of a declared variable, this gives Rust an advantage over some other programming languages, this type of immutability improves the safety and concurrency of Rust programs.
In the code block below, we try to change the value of the variable b
but when you try to run the code, you will get a compiler error indicating that b is an immutable variable.
let b = 9;
println!("The value of b is: {b}");
If you want to change a value of a variable in Rust, you have to explicitly tell Rust that you want to change the value of the variable by declaring the variable to be mutable.
This mutability is also useful in programs that need to dynamically change values of a variable, depending on user’s input or some other scenario.
Check the code block below and see how to make a variable mutable in Rust.
let mut b = 8;
println!("The value of b is: {b}");
b = 39;
println!("The value of b is: {b}");
Try to run the code block, you will get the two values printed, and in the second print value, the new value of b
will be 39. This means that you have been able to change the value of the variable b successfully.
What are Constant Variables in Rust?
Like every other programming language, constants in Rust are always immutable, and in contrasts to variables, you cannot change the values of constants with the mut
keyword.
This immutability property of constants is useful for programs where you do not expect the values of a constant to change in anyway.
To declare a constant in Rust, you use the const
keyword, and a distinct property of constants in Rust is that you must annotate the data type of the const
.
const NUM_OF_ATTENDEES: u32 = 100;
Constants also can be declared anywhere in your code and can be referenced in any part of your code; this makes them globally accessible opposite to variables that are not globally accessible.
One last major difference between constants and variables is that constants can only be set to a const expression, and not the result of a value that can only be computed at run time, that is, before you can declare a constant and for such a constant to be valid, the value of the constant must be known at compile time.
Further explanation, constants cannot be set to depend on input or output of a program.
Check for how to declare a valid const
below.
const MAX_POINTS: u32 = 500;
An example of an invalid constant declaration is the one blow which can only be evaluated at runtime.
const RANDOM_USERS: u32 = get_random_users(); // Invalid, as `get_random_users()` is computed at runtime
What is shadowing in Rust?
In a situation where you want to reuse a variable name for some other purpose, you can use shadowing to do this, shadowing allows you to shadow a variable by another second variable.
For example, in the code block below, we can make a shadow of the initial
variable by setting it to another value that can also be used, in this way, the compiler will always take note of the last value that the variable is set to and that is what it will actually make use of.
let initial = 20;
let initial = 20 + 1;
println!("The value of initial is: {initial}"):
When you run the code above, what you will get on your terminal is 21
which is the value of the shadowing of the initial variable.
Another usage of Shadowing is when you want to use a variable in a scope that is different from the initial scope of the variable, this will create a shadow copy of the variable and isolate it from the initial scope, thereby maintaining the immutability of the base variable.
Look at how this is done below using the combination of the variable in the previous example and a new variable scope.
let initial = 20;
let initial = 20 +1;
{ let initial = initial *30;
println!("The value of the initial variable has been updated in this scope to: {initial}");
}
println!("The value of initial is: {initial}");
When you run the code block above, you will get two values, which are the value of the initial
variable in the inner scope created, and also the last value of the initial
variable that was declared immediately before the scope.
Another usage of shadowing is that it can be used to change the data type of a variable to another type without expressly writing long lines of code to do that.
Here is a common example of changing a variable data type by shadowing the variable.
let x = " ";
let x = x.len();
The first variable above will return a string
while the second variable will return an integer
data type.
What are Rust Data types?
Rust is a statically typed programming language; this makes it mandatory for you to specify the data types you are working with before your programs can be compiled successfully.
This is one of the ways that Rust ensures that there are no conflicts with the data that you get as an output, imagine a programing language that takes in a string
data type, and after compilation, it returns an unsigned integer u32
. This can lead to issues like memory leak and fake data output, Rust is designed to prevent this.
There are two major data types in Rust, and they are:
- Scalar Types
- Compound Types
Scalar type data are those that represent a single vale. There are four Scalar types of data types in Rust:
- Integers
- floating-point
- Booleans
- Characters
Integer Types
An integer is a number that does not have a decimal or fraction, it is a whole number that can either be a positive number, a negative number, or even a zero number.
Rust integers can either be a signed or unsigned integer, and they have different number of bits they occupy.
A signed integer indicates the possibility of the integer to be of a negative value, in that case, there must be a sign that indicates that, while an unsigned integer indicates that the number will always be a positive value.
An Arch integer is based on the types of a computer architecture, and they are either 32-bit size or 64-bit size.
The table below shows the types and sizes of integers in Rust.
Length | Signed | Unsigned |
---|---|---|
8-bit | i8 | u8 |
16-bit | i16 | u16 |
32-bit | i32 | u32 |
64-bit | i64 | u64 |
128-bit | i128 | u128 |
arch | isize | usize |
Floating-Point Types
The floating-point numbers in Rust are numbers with decimals and they are two types: the f32
and f64
. The default floating-point type is f64
, and any decimal number in the Rust programming are always in f64
bits, unless otherwise specified.
Look at the examples below, in the first variable, the floating type is not specified, and by default it is f64
while in the second example, the floating type is indicated to be f32
.
let variable_one = 2.0; //f64
let variable_two: f32 = 7.5; //f32
Boolean Types
There are no other ways to denote Boolean types in Rust except as either true
or false
. These are the default Boolean types that are specified with the bool
keyword. The example below is an illustration of how to use the Boolean types in Rust.
let is_true: bool = true;
let is_false: bool = false;
Character Type
The character type in rust is simply declared by setting the char
variable in quotation. The code block below illustrates the different ways of declaring the character types in Rust.
let a = 'a';
let b: char = 'B';
let smiling_face = '😊';
Compound Types
As the name suggests, compound types are used to group multiple value items into a single type. The two compound types in Rust are: tuples and arrays.
Tuple Type
The tuple type is used to group values of different data types into one, to create a tuple, you must declare the data types of each element in the tuple, separated by a comma.
Tuples have fixed lengths, thus, as soon as they are declared, they cannot change in size in whatever way. The example below is how to declare a tuple in Rust.
let tuple_data:(i32, f64, u8, char) = (-50, 5.5, 1, 'A');
Array Type
Arrays in Rust are also collections of multiple values into a single array, in Rust, all the elements of an array must be of the same data types.
Arrays in Rust have fixed lengths, as such, you cannot modify the size of an array, to have such a collection of arrays that can be modified, you can use a vector
collection instead.
The example below is how to create an array in Rust.
let array = [1, 2, 3, 4, 5];
Another way to initialize an array in Rust is as shown in the code snippet below, but this time around, you want to initiate an array with the same values all through.
let array = [7; 6];
To access the elements in a Rust array, you use indexing method by indicating the index of an element you want to access as shown below.
let new_array = [4, 5, 6, 7, 9, 0];
let first_element = new_array[0];
let second_element = new_array[1];
When you run the program to print the first and second elements in the array above, you will get the results according to the index specified.
Lastly on Arays, in Rust, you cannot access and invalid Array element, this is one of the memory safety provisions in Rust, a program where you try to access an invalid array element will always panic and will not run until you resolve the error indicated by the Rust engine.
Conclusion
In Rust, variables and data types are the basics for safe, efficient programming. In this article, we leant about the various ways to work with variables and create standard programs. With all these safety measures in Rust, it prevents common programming errors at compile time.
Understanding primitive types (integers, floats, Booleans) and compound types (tuples, arrays, strings) prepares you for advanced concepts.
Top comments (0)