Datatype in Rust

A Datatype is the type of value a variable can take. Datatype signifies whether the value which is going to be stored in the variable will be of integer type, character type, boolean type, etc. It is important to classify the type of data to know which kind of mathematical, logical or relational operation can be performed on the variable.

A datatype also defines the bit size of a variable, which means how many bits are required to store the value of a variable in a memory location.

The importance of datatype lies in the fact, that when the same programming languages is made to run in different machines or platforms, the datatype is the one which will take care of the variable type and maintain consistency.

There are certain operations, functions, and modules which are created to work directly based on the datatypes of the variable.

For example, there are constructors which can be pre-defined with a particular datatype, now when the constructor is invoked, automatically, the constructor will work on the data which matches its datatype. This is one example, how a datatype can be important.

Primitive Data Types

Primitive Data types are the data type which is built into a programming language itself and can be used to derive different data type.

bool The boolean type.
char A character type.
i8 The 8-bit signed integer type.
i16 The 32-bit signed integer type.
i32 The 64-bit signed integer type.
i64 The pointer-sized signed integer type.
isize The pointer-sized signed integer type.
u8 The 8-bit unsigned integer type.
u16 The 16-bit unsigned integer type.
u32 The 32-bit unsigned integer type.
u64 The 64-bit unsigned integer type.
usize The pointer-sized unsigned integer type.
f32 The 32-bit floating point type.
f64 The 64-bit floating point type.
array A fixed-size array, denoted [T; N], for the element type, T, and the non-negative compile-time constant size, N.
slice A dynamically-sized view into a contiguous sequence, [T].
str String slices.
tuple A finite heterogeneous sequence, (T, U, ..).

Details and declaration types of each of the data types:

bool

A standard boolean data type. It can be either true or false.

let t = true;
let f = false;
char

It is a 4-byte character.

let a = 'a';
let b = 'b';
let keyboard = '⌨';
integer

The integer data types include i8, i16, i32, i64, isize, u8, u16, u32, u64 , usize. Here, i means signed and u means unsigned. isize and usize depend on the word size of the machine, that is on the architecture of the machine.

let a = 5;
let count = 42;
let mobile = 8675309;
floating point

It includes f32 and f 64.

let pi = 3.14;
let e = 2.718;
array

An array is a fixed sized collection of same type elements. It is declared in the below format:

let name: [type, size] = [attribute1, attribute2, attribute3, attribute4.. etc];
fn main()
{
let array: [i32; 5] = [0, 1, 2, 3, 4];

println!("The first element of the array is: {}", array[0]);

let mut counter = 0;
for x in array.iter(){
    println!("The element at index {} is {}", counter, x);
    counter += 1;
}
}

Program Output:

array-in-rust

slice

A slice is a dynamically sized collection, which is addressed in a contagious memory location.

fn main()
{
let array: [i32; 5] = [0, 1, 2, 3, 4];

let slice = &array[0..3]; 

for x in slice {
	println!("x is {}", x);
}
}

Program Output:

slice-in-rust

In the above declaration, the slice will return 0 to 2. The first index will be inclusive and the second index will be exclusive.

str

A str is the string slice and is the most primitive data types.

let str = "Welcome to your first Rust string";
tuple

Tupes are finite heterogenous, sequences. Tuples have a fixed size and a fixed number of elements. In the array, it contains data of the same type, but in the tuple there can we have different kinds of data types.

fn main()
{
let tuple = ("hello world", 42, "world", [3,6,9]);

println!("First element is {}", tuple.0);
println!("Second element is {}", tuple.1);
println!("Third element is {}", tuple.2);
let mut counter = 0;
for x in &tuple.3 {
    println!("Element {} of the fourth element is {}", counter, x);
    counter += 1;
}
}

As we have seen in the program, inside the tuple we are able to define strings, an integer number, as well as an array, can be inserted inside the tuple.

Program Output :

tuple-in-rust

Variables and Mutability

By default, the variables are immutable in Rust, which means once the variable is assigned one value, it cannot be assigned another or different value in the same program. If we want to do that, then we have to mute the first assigned variable and then the same variable can be assigned again with a different value.

Consider the program below:

fn main() {
    let x = 5;
    println!("The value of x is: {}", x);
    x = 6;
    println!("The value of x is: {}", x);
}

Since the variable x is assigned again, therefore, the compiler will create an error stating that the immutable variable cannot be assigned again. The error will look like this:

error[E0384]: cannot assign twice to immutable variable `x`
 --> main.rs:4:5
 
   let x = 5;
   - first assignment to `x`
    println!("The value of x is: {}", x);
    x = 6;
      ^^^^^ cannot assign twice to immutable variable

error: aborting due to previous error

For more information about this error, try `rustc --explain E0384`.

In the program above, we have seen that the x is assigned value 5 and again x is assigned 6. Now, the compiler will create an error, because of the same variable x is assigned twice.

Now to overcome this error, we can use the keyword mut to mute the variable and then the same variable can be used again. Let us see how it can be done in the program below:

fn main() {
    let mut x = 5;
    println!("The value of x is: {}", x);
    x = 6;
    println!("The value of x is: {}", x);
}

After the variable is muted and compiled again, the program will run fine:

muted-variable

Variables Vs Constants

Variables are the ones whose value can be changed. In Rust, of course, the value of the variable cannot be changed, as in default it's immutable, but we can mute it and change the value.

On the other hand, in the in case of the constants, the value assigned to it, remains the same through the program and by no means, the value can be changed.

A constant in Rust can be declared in this way:

const VALUE: U16= 500;

It may be noted that the immutable variables and constants may look similar. But when we are concerned about the scope, then variables are valid only in their scope, that is where it has been declared. On the other hand, the constants are global and can be accessed from anywhere inside the program.

Shadows

Shadowing a variable means creating a new variable with the same name as the existing variable. We can do this using the keyword let. Usually, the variable in the same name cannot be assigned a different value again, unless we mute it. But shadowing is a different concept.

Here, we are creating the same variable name again, but with a totally new data type and different memory location. For this to happen, every time, we have to use the keyword let, Let us consider the example below:

fn main() {
    let x = 5;
    let x = x + 1;
    let x = x * 2;
    println!("The value of x is: {}", x);
}

Program Output :

shadows-in-rust

The idea behind is, the program first binds x to a value 5.

Now in the second line let x= x+1; , the x after the assignment operator is the original value, that is containing 5. And the x after the let, which is in the left-hand side if the assignment operator, is a brand-new variable created with the same name.

So, now the new variable x, stores the old value of x plus 1. It seems the same value has been updated, but actually, only its shadow is updated. So, in this way, the program output is 12.

This is called Shadowing.

Let us see another example of shadowing. Consider the program below:

let spaces = "   ";
let spaces = spaces.len();

In this program, we have seen that the first variable called spaces consists a string datatype and the second variable whose name is also spaces now contains the number of spaces as it is concatenated with the function called len().

Therefore, it is clear, that not only the variable can be used twice, but also the same variable's data type can be changed using the concept of shadowing.

Comments in Rust

There is not much to be discussed in this section. Comments are those lines or statements inside the program which are ignored by the compiler and does not have any effect on the execution of the program.

Comments can be put inside the program, just by adding // (two forward slashes) after the program statement and can be left without an ending tag on the same line. The compiler considers it as a command.

fn main() {
    println!("Hello, world!");    // This line prints the string inside the double inverted comma. This is called comment.

    my_function();        
}

my_function() {       
    println!("Hello Chercher.tech !");
}
Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions