# Introduction To Rust - Part 1

#### What is Rust?

Rust is a language empowering everyone to build reliable and efficient software. rust created by Graydon Hoare and many others around 2006 while Hoare was working at Mozilla Research. It gained enough interest and users that by 2010 Mozilla had sponsored the development efforts

[https://survey.stackoverflow.co/2022/#technology-most-loved-dreaded-and-wanted](https://survey.stackoverflow.co/2022/#technology-most-loved-dreaded-and-wanted)

StackOverflow 2022 - it's the seventh year as the most loved programing language with 87% of developers saying they want to continue using it.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671036539634/C7R8KV-3-.png align="center")

the language is syntactically similar to C, so you'll find things like for loops, semicolon-terminated statements and curly braces denoting block structures, Rust can guarantee memory safety through the use of a borrow checker that tracks which part of a program has safe access to a different part of memory. This track does not come at the expense of performance, though. Rust programs compile to native binaries and often match or beat the speed of programs written in c or c++ for this reason, Rust is often described as a system programing language that has been designed for performance and safety.

#### To start, You'll need to install Rust

one of the easy ways to install, upgrade, and manage Rust using

the rustup tool .it works equally well on Windows, Linux or macOS.

```bash
 curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

if you have already installed `rustup` , you might want to run `rustup update` to get the latest version of the language and tools, as Rust updates in about six weeks. execute `rustup doc` to read volumes of documentation. you can check your version of `rustc` compiler with the following command.

```bash
rustc --version 
rustc 1.68.0-nightly (b70baa4f9 2022-12-14)
```

#### Getting Started with "Hello, World! "

It's universal truth everybody starts their journey with the hello world program.

create `hello.rs` file with the following content :

```rust
fn main(){
     println!("hello,world!");
}
```

*   functions are defined using fn the name of this function in main.
    
*   `println` is a micro and will print txt to STDOUT.
    
*   the body of the program is enclosed in curly braces.
    

rust will automatically start in the main function. function parameter appears inside the parentheses that follow the name of the function. because there is no argument lists in `main()` . the function takes no arguments.

to run this program, you must first use rust compiler, `rustc` to compile the code.

```rust
$ rustc hello.rs
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671133395013/eMEjizzYK.png align="center")

on macOS, you can use the file command to see what kind of file this is

```bash
rustlabs file hello
hello: Mach-O 64-bit executable arm64
```

you can execute your program like this on mac

```bash
rustlabs ./hello
hello,world!
```

The dot(.) indicates the current directory

you can execute your program like this if your using windows

```bash
rustlabs ./hello.exe
hello,world!
```

🍾 cheers!

##### quiz

1.  What is the keyword for declaring a function?
    

*   fun
    
*   function
    
*   func
    
*   fn
    

1.  What is the output of the following code?
    

```rust

fn main() {
    println!("Hello World!")
    println!("Hello");
}
```

a) Hello World! Hello b) error hint:- A semicolon can be omitted at the end of the last statement only.

#### Organizing a Rust Project :

for any project, we all write multiple source files and execute them as a single binary. let's remove our existing hello binary `rm hello`

let's create a parent directory

```bash
$ mkdir -p hello/src
```

now move the `hello.rs`source file into `hello/src` using the mv command

```bash
$ mv hello 
$ rustc src/hello.rs
```

check the content of the directory using `tree` command :

```bash
➜  rustlabs tree
.
└── hello
    └── src
        └── hello.rs
```

#### Basic Formatting

A single placeholder is used when it is required to print a single value.

```rust
fn main() {
    println!("Number: {}", 1);
}
```

We can use multiple placeholders within the `println!()` macro. The number of placeholders should be equal to the number of values to be printed.

```rust
fn main() {
    println!("{} is a {} Community", "Join", "CloudNativeFolks");
}
```

Positional arguments specify the positions of the values in a sentence.

```rust
fn main() {
    println!("Enhance your coding skills from {0} Track. {0} by {1}", "Rustlabs ", " CloudNativeFolks");
}
```

A placeholder can take a named argument and assign it a value explicitly. It does this by specifying a name within the placeholder and assigning that name the value to be inserted in the string.

```rust
fn main() {
    println!("{workshop} by {Community} ", Workshop = "Rust", Commmunity = "CloudNativeFolks");
}
```

If we want to convert the value to binary, hexadecimal, or octal write:

```rust
{:b},{:x},{:o}
```

In the placeholder for binary, hexadecimal, or octal respectively and in the value specify the number. You can use all three of them or one of them in a single expression.

```rust
fn main() {
    println!("Number : 10 \nBinary:{:b} Hexadecimal:{:x} Octal:{:o}", 10, 10, 10);
}
```

If we want to convert the value to binary, hexadecimal, or octal write:

```rust
{:b},{:x},{:o}
```

In the placeholder for binary, hexadecimal, or octal respectively and in the value specify the number. You can use all three of them or one of them in a single expression.

```rust
fn main() {
    println!("Number : 10 \nBinary:{:b} Hexadecimal:{:x} Octal:{:o}", 10, 10, 10);
}
```

We can perform basic math and the placeholder gets replaced with the result.

```rust
fn main() {
    println!("{} + {} = {}",10, 10, 10 + 10);
}
```

#### Placeholder for debug trait

```rust
fn main() {
    println!("{:?}", ("This is a Rustlabs", 101));
}
```

#### Printing style

The table below summarizes the macros used to print in Rust.

| macro | Printing Style |
| --- | --- |
| `print!()` | prints strings to console |
| `println!()` | same as `print!()` but also appends a new line character at end of the string |
| `eprint!()` | prints anything within the parentheses as an error |
| `eprintln!()` | same as `eprint!()` but also appends a new line character at the end |

Let’s discuss each of the macros in detail.

The `print!()` the macro simply prints the output to the console. The following example prints “RustLabs by CloudNativeFolks Community ” in one line

```rust
fn main() {
    print!("RustLab ");
    print!(" by CloudNativeFolks Community ");
}
```

#### `println!()`

The `println!()` macro appends a new line at the end of the string.

The following example prints “RustLabs” on one line and “by CloudNativeFolks Community” on the new line.

```rust
fn main() {
    println!("RustLabs");
    println!("by CloudNativeFolks Community");
}
```

#### `eprint!()`

The `eprint!()` macro displays the output as an error.

The following example prints “RustLabs” and “by CloudNativeFolks Community” on the same line but as an error.

```rust
fn main() {
    eprint!("RustLabs);
    eprint!("by CloudNativeFolks Community");
}
```

#### `eprintln!()`

The `eprint!()` macro displays the output as an error and appends a new line(\\n) at the end of it.

The following example prints “RustLabs” as an error and appends a new line to it. Then prints “by CloudNativeFolks Community” and appends a new line.

```rust
fn main() {
    eprintln!("RustLabs");
    eprintln!("by CloudNativeFolks Community");
}
```

📝Note: `eprint!()` and `eprintln!()` come in handy when we want to indicate to the user that an error condition has occurred.

#### Types of Comments in Rust

Rust has two types of comments that are commonly used:

#### Line Comments `//`

The comments followed by a double forward slash, `//`, are known as line comments.

This is the most recommended style of comment for commenting a single line.

```rust
// Writing a Rust program
fn main() {
    //The line comment is the recommended comment style
    println!("This is a line comment!"); // print hello World to the screen
}
```

#### Block Comments `/*...*/`

Text enclosed within `/*...*/` is known as a block comment.

This is used for temporarily disabling a large chunk of code.

#### Doc Comments

The comments followed by `///` or `//!` are known as doc comments. Let’s see the difference between the two sets of doc comments.

#### Outer Doc Comments `///`

Outer doc comments are written outside the block of code.

This type of comment supports markdown notation. This is used to generate docs referring to the following item.

#### Inner Doc Comments `//!`

Inner doc comments are written inside the block of code.

This comment style is used to generate docs referring to the item within a block of code.

```rust
/// This is a Doc comment outside the function
/// Generate docs for the following item.
/// This shows my code outside a module or a function
fn main() {
    //! This a doc comment that is inside the function   
    //! This comment shows my code inside a module or a function  
    //! Generate docs for the enclosing item
    println!("{} can support {} notation","Doc comment","markdown");
}
```

#### Variables

A variable is like a storage box paired with an associated name which contains data. The associated name is the identifier and the data that goes inside the variable is the value. They are immutable by default, meaning, you cannot reassign value to them.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671314377465/abCTBMPR2.png align="center")

#### **Create a Variable**

To create a variable, use the let binding followed by the variable name.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671314469147/XSlALG76v.png align="center")

*   What is binding?  
    Rust refers to declarations as bindings as they bind a name at the time of creation. let is a kind of declaration statement.
    
*   Naming Convention: By convention, you would write a variable name in a snake\_case i.e., - All letters should be lower case. - All words should be separated using an underscore `( _ )`.
    

#### **Initialize a Variable**

A variable can be initialized by assigning a value to it when it is declared. The value is said to be bound to that variable.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671315044216/ai-g5G4a4.png align="center")

Note: It’s possible to declare the variable first and assign it a value later. However, it is not recommended to do this as it may lead to the use of uninitialized variables.

The example below declares a variable, language, and initializes it with a value, Rust, and then displays the value of a said variable:

```rust
fn main() {
    let language = "Rust"; // define a variable
    println!("Language: {}", language); // print the variable
}
```

#### **What if You Want to Make a Variable Mutable?**

At the beginning of this lesson, it was mentioned that a variable is immutable until you want to make a change in the variable, then it can be made mutable. To make a variable mutable, write let followed by the `mut` keyword and the variable name:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671315234953/oOOFcQwP8.png align="center")

```rust
fn main() {
    let mut language = "Rust"; // define a mutable variable
    println!("Language: {}", language); // print the variable
    language = "Java"; // update the variable
    println!("Language: {}", language); // print the updated value of variable
}
```

**Assigning Multiple Variables**

It is possible to assign multiple variables in one statement.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671317641726/EKd6Jcy-Q.png align="center")

```rust
fn main() {
    let (language,community) =("Rust","CloudNativeFolks"); // assign multiple values
    println!("This is a {} labs by {}.", language ,CloudNativefolks ); // print the value
}
```

Note: If a variable is kept un-assigned or unused, you’ll get a warning. To remove such a warning write the expression `#[allow(unused_variables, unused_mut)]` at the start of the program code. However, it’s not a good practice to keep unassigned/unused variables.

**Scope and Shadowing**

The scope of a variable refers to the visibility of a variable, or , which parts of a program can access that variable.  
It all depends on where this variable is being declared. If it is declared inside any curly braces `{}`, i.e., a block of code, its scope is restricted within the braces, otherwise, the scope is global.  
**Types of Variables**  
There are two types of variables in terms of scope.  
**\- Local Variable**  
A variable that is within a block of code, `{ }`, that cannot be accessed outside that block is a local variable. After the closing curly brace, } , the variable is freed and memory for the variable is deallocated.  
\- **Global Variable**  
The variables that are declared outside any block of code and can be accessed within any subsequent blocks are known as global variables.  
The variables declared using the const keyword can be declared in local as well as a global scope.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671318639758/GSXQKynjG.png align="center")

Note: The following code gives an error, ❌, since the variable created inside the inner block of code has been accessed outside its scope.

```rust
fn main() {
  let outer_variable = 112;
  { // start of code block
        let inner_variable = 213;
        println!("block variable inner: {}", inner_variable);
        println!("block variable outer: {}", outer_variable);
  } // end of code block
    println!("inner variable: {}", inner_variable); // use of inner_variable outside scope
}
```

output

```rust
rror[E0425]: cannot find value `inner_variable` in this scope
 --> main.rs:8:36
  |
8 |     println!("inner variable: {}", inner_variable); // use of inner_variable outside scope
  |                                    ^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `outer_variable`

error: aborting due to previous error
```

To fix this error, the variable declaration can be moved outside the inner block of code. That way, the scope of the variable spans the entire main() function. This is shown below:

```rust
fn main() {
  let outer_variable = 112;
  let inner_variable = 213;
  { // start of code block
        println!("block variable inner: {}", inner_variable);
        println!("block variable outer: {}", outer_variable);
  } // end of code block
    println!("inner variable: {}", inner_variable);
  }
```

output

```rust
block variable inner: 213
block variable outer: 112
inner variable: 213
```

**Shadowing**

Variable shadowing is a technique in which a variable declared within a certain scope has the same name as a variable declared in an outer scope. This is also known as masking. This outer variable is said to be shadowed by the inner variable, while the inner variable is said to mask the outer variable.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671318926387/zHK5mO3VE.png align="center")

The following code explains the concept.

```rust
fn main() {
  let outer_variable = 112;
  { // start of code block
        let inner_variable = 213;
        println!("block variable: {}", inner_variable);
        let outer_variable = 117;
        println!("block variable outer: {}", outer_variable);
  } // end of code block
    println!("outer variable: {}", outer_variable);
  }
```

output

```rust

block variable: 213
block variable outer: 117
outer variable: 112
```

**What Are Data Types?**  
\- Data Type  
Rust is a statically typed language, meaning, it must know the type of all variables at compile time.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671319107080/0IFj8DVlo.png align="center")

**How to Define a Type in Rust?**  
We can define a variable in rust in two different ways:  
\- Implicit Definition  
Unlike other languages like C++ and Java, Rust can infer the type from the type of value assigned to a variable.

The general syntax is :

```rust
let variable name = value ;
```

**Explicit Definition**

Explicitly tells the compiler about the type of variable.  
The general syntax is:

```rust
let variable name : data type = value ;
```

**Primitive Types**  
Rust has a couple of types that are considered primitive. That means they are built-in into the language. There are different data types used for different purposes.  
The following illustration shows the different primitive data types in Rust:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671319300876/JM7c3o5zv.png align="center")

\*\*  
Scalar Type\*\*

They store a single value.

\- Below is the list of scalar types:

\- Integers

\- Floats

\- Boolean

\- Character

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671319655036/baJbPWMUI.png align="center")

**Compound Type**  
They group multiple values in one variable. Below is the list of compound types:-

\- Array

\- Tuple

#### Numeric Types - Integers and Floats

*   Integers
    
    Variables of Integer data type hold whole number values. There are two subtypes of integer data type in Rust, based on the number of bits occupied by a variable in memory.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671319832574/uAP-jhubU.png align="center")

*   Fixed Size Types
    
    The fixed integer types have a specific number of bits in their notation. This notation is a combination of a letter and a number. The former denotes the category of the integer, whether it is, unsigned or signed, and the latter denotes the size of an integer, i.e., 8, 16, 32, 64.
    
*   Below is the list of fixed-length integer types:
    
    *   i8: The 8-bit signed integer type.
        
    *   i16: The 16-bit signed integer type.
        
    *   i32: The 32-bit signed integer type.
        
    *   i64: The 64-bit 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.
        

#### Variable Size Types

The integer type in which the particular size depends on the underlying machine architecture.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671320103025/jEJ7BfJPO.png align="center")

💡 Why are there so many types of integers and how do you pick a data type?

The choice depends on what values a variable is expected to hold. So, a programmer should pick a data type that is not so small that the data is lost. Nor should they pick a data type that is so big that it wastes memory.

isize: The pointer-sized signed integer type. usize: The pointer-sized unsigned integer type

**Example**  
The code below defines an integer type both explicitly and implicitly:  
\- Explicit Definition  
The following code explicitly defines the integer variables using the integer type fixed or variable):

```rust
fn main() {
    //explicitly define an integer
    let a:i32 = 24;
    let b:u64 = 23;
    let c:usize = 26;
    let d:isize = 29;
    //print the values
    println!("a: {}", a);
    println!("b: {}", b);
    println!("c: {}", c);
    println!("d: {}", d);
    
}
```

output

```rust
a: 24
b: 23
c: 26
d: 29
```

#### Implicit Definition

The following code implicitly defines the integer type of the variable by assigning an integer value to the variable.

```rust
fn main() {
    //explicitly define an integer
    let a = 21; 
    let b = 1;
    let c = 54;
    let d = 343434;
    //print the variable
    println!("a: {}", a);
    println!("b: {}", b);
    println!("c: {}", c);
    println!("d: {}", d);
    
}
```

output

```rust
a: 21
b: 1
c: 54
d: 343434
```

#### Floating Point

Floating-point numbers refer to numbers with a fractional part.  
The representation of floating-point numbers in a computer’s memory is such that the precision with which a number is stored in memory depends on the number of bits used for storing the variable.  
In this respect, there are two subtypes: single-precision f32 and double-precision f64 floating-point, with the latter having more bits to store the number.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671320658296/_KJ-RoYQE.png align="center")

*   f32: The 32-bit floating point type.
    
*   f64: The 64-bit floating point type.
    

**Example**

The code below defines a floating-point number both explicitly and implicitly:

*   Explicit Definition
   

The following code explicitly defines the float variable using the float type (f32 or f64)

```rust
fn main() {
    //explicitly define a float type
    let f1:f32 = 32.9;
    let f2:f64 = 6789.89;
    println!("f1: {}", f1);
    println!("f2: {}", f2);
}
```

output

```rust
f1: 32.9
f2: 6789.89
```

#### Implicit Definition:

The following code implicitly defines the float type of the variable by assigning a floating-point value to the variable:

```rust
fn main() {
    //implicitly define a float type
    let pi = 3.14;
    let e = 2.17828;
    println!("pi: {}", pi);
    println!("e: {}", e);
}
```

output

```rust
pi: 3.14
e: 2.17828
```

#### Boolean

The boolean variable can take a value of either true or false. The following code explains how to define a boolean variable in three different ways:

*   Explicit Definition The following code explicitly defines the variable using the bool keyword:
    
    ```rust
    n main() {
        //explicitly define a bool
        let is_bool:bool = true;
        println!("explicitly_defined: {}", is_bool);
    }
    ```
    
    output `rust explicitly_defined: true`
    
    *   **Implicit Definition**
        
        The following code implicitly defines the boolean type of a variable by assigning the value true or false to the variable.
        
        ```rust
        fn main() {
            // assign a boolean value
            let a = true;
            let b = false;
            println!("a: {}", a);
            println!("b: {}", b);
        }
        ```
        

**Result of an Expression**  
The result of an expression that evaluates to either true or false (for example a comparison of two values) can be assigned to an implicit boolean variable

```rust
fn main() {
    // get a value from an expression
    let c = 10 > 2;
    println!("c: {}", c);
}
```

#### Character and String

*   Character
    

The variable is used to store a single character value, such as a single digit or a single alphabet. The value assigned to a char variable is enclosed in a single quote('').

Note: Unlike some other languages, a character in Rust takes up 4 bytes rather than a single byte. It does so because it can store a lot more than just an ASCII value like emojis, Korean, Chinese, and Japanese characters.

#### Example

The code below defines a character both explicitly and implicitly:

*   Explicit Definition
    

The following code explicitly defines the variable using the char keyword:

```rust
fn main() {
    // explicitly define 
    let char_1:char = 'e';
    println!("character1: {}", char_1); 
}
```

Output

```rust
character1: e
```

Implicit Definition

The following code implicitly defines the character type of the variable by assigning the single value enclosed within single quotes to them.

```rust
fn main() { 
    // implicitly define
    let char_2 = 'a';
    let char_3 = 'b';
    println!("character2: {}", char_2);
    println!("character3: {}", char_3);
}
```

Output

```rust
character2: a
character3: b
```

#### String

A string is any sequence of characters enclosed within double quotes (" ").

#### Example

The code below defines a string both explicitly and implicitly:

*   Explicit Definition
    

The following code explicitly defines the variable using the `&str` keyword:

```rust
fn main() {
    // explicitly define 
    let str_1:&str = "Rust Programming";
    println!("String 1: {}", str_1); 
}
```

Output

```rust
String 1: Rust Programming
```

#### Implicit Definition

The following code implicitly defines the string type of the variable by assigning the single value enclosed within double quotes to them.

```rust

fn main() { 
    // implicitly define
    let str_2 = "Rust Programming";
    println!("String 2: {}", str_2);
}
```

output:-

```rust
String 2: Rust Programming
```

#### Arrays

*   What Is an Array?
    

An array is a homogenous sequence of elements. Being a compound type, it is used when the collection of values of the same type is to be stored in a single variable. In Rust, an array can only be of a fixed length. Like all other languages, each element in the array is assigned an index. By default, the first element is always at index 0.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671366378317/NFn0ZUdam.png align="center")

Note: By default, arrays are immutable.

#### Define an Array

To define an array in Rust, we have to define the type and size of the array. To initialize an array, the array elements are enclosed in square brackets `[]`. The following illustration explains the concept:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671366448928/IvLIJ_AJQ.png align="center")

```rust
#[allow(unused_variables, unused_mut)]
fn main() {
   //define an array of size 4
   let arr:[i32;4] = [1, 2, 3, 4]; 
   // initialize an array of size 4 with 0
   let arr1 = [0 ; 4]; 
}
```

*   The array arr declaration on line 4 declares an array with elements 1,2,3,4.
    
*   The array arr1 declaration on line 6 implicitly determines the data type (integer) from the value 0 and 4, is the size of the array. So, this becomes an array consisting of 4 zeros.
    

**Access an Element of an Array**  
\- Any value of the array can be accessed by writing the array name followed by the index number enclosed within square brackets `[ ]`.

```rust
fn main() {
   //define an array of size 4
   let arr:[i32;4] = [1, 2, 3, 4]; 
   //print the first element of array
   println!("The first value of array is {}", arr[0]);
   // initialize an array of size 4 with 0
   let arr1 = [0; 4]; 
   //print the first element of array
   println!("The first value of array is {}", arr1[0]);
}
```

output

```rust
The first value of array is 1
The first value of array is 0
```

**How to Make an Array Mutable?** Just like a variable becomes mutable by adding the mut keyword after let, the same goes for an array.

```rust
fn main() {
    //define a mutable array of size 4
    let mut arr:[i32;4] = [1, 2, 3, 4]; 
    println!("The value of array at index 1: {}", arr[1]);
    arr[1] = 9;
    println!("The value of array at index 1: {}", arr[1]);
}
```

output

```rust
The value of array at index 1: 2
The value of array at index 1: 9
```

**Print the Array** The whole array can be traversed using a loop or the debug trait.

```rust
fn main() {
    //define an array of size 4
    let arr:[i32;4] = [1, 2, 3, 4]; 
    //Using debug trait
    println!("\nPrint using a debug trait");
    println!("Array: {:?}", arr);
}
```

output

```rust
Print using a debug trait
Array: [1, 2, 3, 4]
```

**Get the Length of the Array** To access the length of the array, use the built-in function len.

```rust
fn main() {
    //define an array of size 4
    let arr:[i32;4] = [1, 2, 3, 4]; 
    // print the length of array
    println!("Length of array: {}", arr.len());
}
```

**Get Slice**  
Slice is basically a portion of an array. It lets you refer to a subset of a contiguous memory location. But unlike an array, the size of the slice is not known at compile time.

*   Syntax
    
    *   A slice is a two-word object, the first word is a data pointer and the second word is a slice length.
        
    *   Data pointer is a programming language object that points to the memory location of the data, i.e., it stores the memory address of the data.
        
    *   To declare an array slice, we need to specify the name of the source array and the range of elements to be included in the slice. Note: If the range of elements is not specified, it will consider the whole array as a slice.
        

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671366956971/O8WhnH2zz.png align="center")

```rust
 fn main() {
    //define an array of size 4
    let arr:[i32;4] = [1, 2, 3, 4]; 
    //define the slice
    let slice_array1:&[i32] = &arr;
    let slice_array2:&[i32] = &arr[0..2];
    // print the slice of an array
    println!("Slice of an array: {:?}", slice_array1);
    println!("Slice of an array: {:?}", slice_array2);
}
```

output

```rust
Slice of an array: [1, 2, 3, 4]
Slice of an array: [1, 2]
```

**What are Tuples?**  
 - Tuples are heterogeneous sequences of elements, meaning, each element in a tuple can have a different data type. Just like arrays, tuples are of a fixed length.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671367268746/_5zKDP-av.png align="center")

*   Define a Tuple
    

A tuple can be defined by writing let followed by the name of the tuple and then enclosing the values within the parenthesis.

*   Syntax 1
    
    *   The syntax below defines a tuple without specifying the type. However, the compiler can infer the type.
        

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671367326056/cAbHd5U8i.png align="center")

*   Syntax2
    
    *   The syntax below defines a tuple by specifying the type.
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671367374748/8OZjQli32.png align="center")
        

#### Example

The following illustration explains the concept:

```rust
#[allow(unused_variables, unused_mut)]
fn main() {
    //define a tuple
    let person_data = ("Alex", 48, "35kg", "6ft");
    // define a tuple with type annotated
    let person_data : (&str, i32, &str, &str) = ("Alex", 48, "35kg", "6ft");
}
```

*   Access the Value of the Tuple
    
*   Unlike array which uses `[]` for accessing an element, the value of the tuple can be accessed using the dot operator `(.)`.
    
*   `tuplename.indexvalue`
    
*   To get the individual values out of a tuple, we can use pattern matching to destructure a tuple value, like this:
    
    ```rust
    let person_data = ("Alex", 48, "35kg", "6ft");
       let (w, x, y, z) = person_data;
    ```
    
    ```rust
    fn main() {
       //define a tuple
       let person_data = ("Alex", 48, "35kg", "6ft");
       // access value of a tuple
       println!("The value of the tuple at index 0 and index 1 are {} {}",person_data.0,person_data.1);
    
       //define a tuple
       let person_data = ("Alex", 48, "35kg", "6ft");
       // get individual values out of tuple
       let (w ,x, y, z) = person_data;
       //print values
       println!("Name : {}",w);
       println!("Age : {}",x);
       println!("Weight : {}",y);
       println!("Height : {}",z);
    }
    ```
    
    output
    
    ```rust
    The value of the tuple at index 0 and index 1 are Alex 48
    Name : Alex
    Age : 48
    Weight : 35kg
    Height : 6ft
    ```
    

#### How to Make a Tuple Mutable?

Just like a variable becomes mutable by adding the mut keyword after let, the same goes for a tuple.

```rust
fn main() {
    //define a tuple
    let mut person_data = ("Alex", 48, "35kg", "6ft");
    //print the value of tuple
    println!("The value of the tuple at index 0 and index 1 are {} {}", person_data.0, person_data.1);
    //modify the value at index 0
    person_data.0 = "John";
    //print the modified value
    println!("The value of the tuple at index 0 and index 1 are {} {}", person_data.0, person_data.1);
}
```

output:-

```rust
The value of the tuple at index 0 and index 1 are Alex 48
The value of the tuple at index 0 and index 1 are John 48
```

#### Print the Tuple

The whole tuple can be traversed using the debug trait.

```rust
fn main() {
    //define a tuple
    let person_data = ("Alex", 48, "35kg", "6ft");
    //print the value of tuple
    println!("Tuple - Person Data : {:?}",person_data);
}
```

output:-

```rust
Tuple - Person Data : ("Alex", 48, "35kg", "6ft")
```

#### What Are Constant Variables?

*   Constant variables are declared constant throughout the program scope, meaning, their value cannot be modified. They can be defined in the global and local scopes.
    

*   They are declared using the `const` keyword followed by the name of the variable, colon `(:)`, and then the data type of the variable.
    
![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671367633523/6Rhr9z0aP.png align="center")

*   Naming Convention: By convention, you write a constant variable name in a SCREAMING\_SNAKE\_CASE, i.e.,
    
    *   All letters should be UPPER case.
        
    *   All words should be separated using an underscore `( _ )`
   
      The following example defines two const variables:
        
        *   ID\_1 in global scope
            
        *   ID\_2 in local scope
            
        
        ```rust
          const ID_1: i32 = 4; // define a global constant variable
        fn main() {
           const ID_2: u32 = 3; // define a local constant variable
           println!("ID:{}", ID_1); // print the global constant variable
           println!("ID:{}", ID_2); // print the local constant variable
        }
        ```
        output:
        
        ```rust
        ID:4
        ID:3
        ```
        
#### Difference Between const and let Variables

There are many differences between const and let variables.

- Declaration
* Constant variables are declared using the const keyword unlike let variables.
- Scope
* const variables are declared in global and local scope unlike let variables that are declared only in the local scope.
-  Mutability
 * const variable cannot be mutable unlike let which can be made mutable using mut keyword.
-  Data Type
*Unlike let variables, it is mandatory to define the data type of const variables.
* Set Value at Run-time
* The value of const variable can only be set before running the program whereas the let variable can store the result at runtime.
-  Shadowing
* Unlike let variables, const variables cannot be shadowed.

#### Introduction to Operators

##### Operators

*   An operator is a symbol that takes one or more values and outputs another. It tells the compiler to perform some sort of operation.
    

##### Types of Operators

*   Different operators are available in Rust for performing different operations. Based on the number of operands, the operators can be categorized into binary and unary operators:
    

##### Unary Operators

*   The operators that act upon a single operand are unary operators.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671367856072/K-kBcCuqC.png align="center")

*   Types
    
    *   Borrow Expression
        
    *   Dereference Expression
        
    *   Negation Expression
        
    *   Logical Negation Expression
        
    
 ##### Binary Operators
    
    *   The operators that deal with two operands are binary operators.
        

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671367916690/hL9SFKvUA.png align="center")

##### Arithmetic Operators

*   What Are Arithmetic Operators?
    
    *   Arithmetic operators are used to perform arithmetic operations.
        
*   Types The table below summarizes the arithmetic operations in Rust.
    

##### Types

The table below summarizes the arithmetic operations in Rust.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671368264480/D_YIJA9Zq.png align="center")

| operator | operation | explanation |
| --- | --- | --- |
| operand1 + operand2 | addition | add operand1 and operand2 |
| operand1 - operand2 | subtraction | subtract operand2 from operand1 |
| operand1 / operand2 | divide | divide operand1 by operand2 |
| operand1 \* operand2 | multiplication | multiply operand1 with operand2 |
| operand1 % operand2 | modulus | get reminder of operand1 by dividing with operand2 |

The following example shows the use of arithmetic operators in a program:

```rust

fn main() {
    let a = 4;
    let b = 3;
    
    println!("Operand 1:{}, Operand 2:{}", a , b);
    println!("Addition:{}", a + b);
    println!("Subtraction:{}", a - b);
    println!("Multiplication:{}", a * b);
    println!("Division:{}", a / b);
    println!("Modulus:{}", a % b);
}
```

output

```rust
Operand 1:4, Operand 2:3
Addition:7
Subtraction:1
Multiplication:12
Division:1
Modulus:1
```

##### Logical Operators

##### What Are Logical Operators?

Logical operators operate on true / false values

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671368317422/PLcIFgd6c.png align="center")

##### Types

The following table summarizes the types and functions of the logical operators:

| operator | operation | explanation |
| --- | --- | --- |
| operand1 && operand2 | AND | Evaluates to true if operand 1 and Operand 2 both evaluates to be true |
| operand1 |  | operand2 |
| ! operand1 | NOT | negates the value of single operand |

The logical AND and OR are known as Lazy Boolean expressions because the left-hand side operand of the operator is first evaluated. If it is false, there is no need to evaluate the right-hand side operand in case of AND. If it is true, there is no need to evaluate the right-hand side operand in case of OR.

The following example shows the use of logical operators in a program:

```rust
fn main() {
  let a = true;
  let b = false;
  println!("Operand 1:{}, Operand 2:{}", a , b);
  println!("AND:{}", a && b);
  println!("OR:{}", a || b);
  println!("NOT:{}", ! a);
}
```

output

```rust
Operand 1:true, Operand 2:false
AND:false
OR:true
NOT:false
```

##### Comparison Operators

##### What Are Comparison Operators?

Comparison Operators are used for comparing the values of two operands.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671368554784/DbnbaLeQx.png align="center")

##### Types

Below is the list of comparison operators in Rust.

| operator | operation | explanation |
| --- | --- | --- |
| operand1 &gt; operand2 | greater then | Evaluates to true if operand 1 is greater then Operand 2 |
| operand1 &lt; operand2 | lesser then | Evaluates to true if operand 1 is lesser then Operand 2 |
| operand1 &lt;= operand2 | less then equal to | Evaluates to true if operand 1 is lesser or equal to the Operand 2 |
| operand1 &gt;= operand2 | greater then equal to | Evaluates to true if operand 1 is greater or equal to the Operand 2 |
| operand1 == operand2 | equal to | Evaluates to true if operand 1 equal to the Operand 2 |
| operand1 != operand2 | Not equal to | Evaluates to true if operand 1 not equal to the Operand 2 |

The following example shows the use of comparison operators in a program:

```rust
fn main() {
    let a = 2;
    let b = 3;
    println!("Operand 1:{}, Operand 2:{}", a , b);
    println!("a > b:{}", a > b);
    println!("a < b:{}", a < b);
    println!("a >= b:{}", a >= b);
    println!("a <= b:{}", a <= b);
    println!("a == b:{}", a == b);
    println!("a != b:{}", a != b);
}
```

output

```rust
Operand 1:2, Operand 2:3
a > b:false
a < b:true
a >= b:false
a <= b:true
a == b:false
a != b:true
```

##### Bitwise Operators

*   What Are Bitwise Operators? Bitwise operators deal with the binary representation of the operands.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671368731149/ATwmNwxM8.png align="center")

Types

The table below summarizes the types of bitwise operators in Rust.

| operator | operation | explanation |
| --- | --- | --- |
| operand1 & operand2 | AND | bitwise AND operand1 and operand2 |
| operand1 | operand2 | OR |
| operand1 ^ operand2 | XOR | bitwise XOR operand1 and operand2 |
| ! operand1 | NOT | Inverse the bit of operand |
| &lt;&lt; operand | Left shift | moves all the operand1 to the left by the number of places specified in the operand 2 |
| new bits filled with zeros . shifting a value left by one position is equivalent to multiplying it by 2 , |  |  |
| Shifting to positions is equivalent to multiplying it by 4 and so on |  |  |
| \&gt;&gt; operand | Right Shift | moves all the operand1 to the right by the number of places specified in the operand 2 |
| new bits filled with zeros . shifting a value right by one position is equivalent to multiplying it by 2 , |  |  |
| Shifting to positions is equivalent to multiplying it by 4 and so on |  |  |

📝 Note: Right shift &gt;&gt; is same as arithmetic right shift on signed integer types, logical right shift on unsigned integer types.

- Example

The example below shows the bitwise AND, OR, XOR, Left Shift, and Right Shift operations.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671368805283/DahG7JUds.png align="center")

The following example shows the use of bitwise operators in a program:

```rust
fn main() {
  let a = 5;
  let b = 6;
  println!("Operand 1: {}, Operand 2: {}", a , b);
  println!("AND: {}", a & b);
  println!("OR: {}", a | b);
  println!("XOR: {}", a ^ b);
  println!("NOT a: {}", !a);
  println!("Left shift: {}", a << 2);
  println!("Right shift: {}", a >> 1);

}
```

output

```rust
Operand 1: 5, Operand 2: 6
AND: 4
OR: 7
XOR: 3
NOT a: -6
Left shift: 20
Right shift: 2
```

#### Assignment and Compound Assignment Operators

*   Assignment Operator The assignment operator is used to save a value in the variable.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671368910082/Np8zilrz4.png align="center")

#### Type

Rust has only one assignment operator, = . The following table defines the function of the operator.

| operator | operation | explanation | example |
| --- | --- | --- | --- |
| operand1 = operand2 | assign a value | assign a value of operand 2 to operand 1 | a = 1 |
| b = a |  |  |  |

The following example demonstrates the use of some of the assignment operator in a program:

```rust
fn main() {
   let a = 2;
   let b = a;
   println!("b = a");
   println!("Value of a:{}", a);
   println!("Value of b:{}", b);
}
```

output:-

```rust
b = a
Value of a:2
Value of b:2
```

##### Compound Assignment Operator

The compound assignment operator is used to perform an operation and then assign that value to the operand.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671369047830/MRNASgOOA.png align="center")

##### Types

The following table summarizes the types of compound assignment operators

| operator | operation | explanation |
| --- | --- | --- |
| operand1 += operand2 |  |  |

operand1 -= operand2 | add a value and assign

subtract a value and assign | add left-hand side to right-hand side and then save updated value to left operand

add right-hand side to right-hand side and then save updated value to left operand | | operand1 /= operand2

operand1 \*= operand2 | divide a value and assign

multiple a value and assign | divide left-hand side to right-hand side and then save updated value to left operand

multiply left-hand side to right-hand side and then save updated value to left operand | | operand1 %= operand2 | modulus and assign | take modulus of the left-hand side with right-hand operand and then save updated value to left operand | | operand1 &= operand2 | Bitwise AND and assign | Bitwise AND of the left-hand side with right-hand operand and then save updated value to left operand | | operand1 |= operand2 | Bitwise OR and assign | Bitwise OR of the left-hand side with right-hand operand and then save updated value to left operand | | operand1 ^= operand2 | Bitwise XOR and assign | Bitwise XOR of the left-hand side with right-hand operand and then save updated value to left operand | | &lt;&lt;= operand1 | left sift and assign | left shift the operand x times then save updated value to operand | | &gt;&gt;= operand1 | right shift and assign | right shift the operand x times then save updated value to operand |

The following example demonstrates the use of some of these operators in a program:

```rust

fn main() {
    //define a mutable variable
    let mut a = 2;
    println!("a:{}", a);
    a += 1;
    println!("a+=1:{}", a);
    println!("a:{}", a);
    a -= 1;
    println!("a-=1:{}", a);
    println!("a:{}", a);
    a /= 1;
    println!("a/=1:{}", a);
    println!("a:{}", a);
    a *= 3;
    println!("a/=3:{}", a);
}
```

output:

```rust
a:2
a+=1:3
a:3
a-=1:2
a:2
a/=1:2
a:2
a/=3:6
```

Type Casting Operator

What Is Type Casting? Type casting is when you convert the data type of the variable to some other data type.

*   Type Casting in Rust In Rust, typecasting is done using the as keyword followed by the desired data type of the variable or value.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671369146333/hjIHKe9pg.png align="center")

The following example demonstrates the use of type casting operator in a program:

```rust

fn main() {
    let a = 15;
    let b = (a as f64) / 2.0; 
    println!("a: {}", a);
    println!("b: {}", b);
}
```

output

```rust
a: 15
b: 7.5
```

📝 What data types can be type casted?

*   Integer can be type casted to floating-point and vice versa.
    
*   Integer can be typecasted to String
    

📝What data types cannot be type casted?

*   String (&str) or character cannot be type casted to the data type of type integer or float.
    
*   Character cannot be type casted to String type and vice versa
    

The following code gives an error, ❌, because of the invalid type casting operation:

```rust
fn main() {
    let a: char = 'r' ; // cannot be type casted
    let b = a as &str ; 
    println!("a: {}", a);
    println!("b: {}", b);
}
```

#### Borrowing and Dereferencing Operators

##### Borrowing Operator

Borrowing means to reference the original data binding or to share the data.References are just like pointers in C.

Two variables are involved in a borrowing relationship when the referenced variable holds a value that the referencing variable borrows. The referencing variable simply points to the memory location of the referenced variable.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671410555933/owLs1MxAu.png align="center")

The following illustration shows that operand 1 borrows the value of operand 2 using two types of operators:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671410641854/lgd0tP_3b.png align="center")

#### Types

Borrowing can be of two types:

*   Shared borrowing
    
*   A piece of data that is shared by single or multiple variables but it cannot be altered
    
*   Mutable borrowing
    
*   A piece of data that is shared and altered by a single variable (but the data is inaccessible to other variables at that time)
    
*   The following table summarizes the function of these two types.
    

| operator | operation | explanation |
| --- | --- | --- |
| Operand1 = & Operand2 | shared borrow | operand 1 can read data of another operand 2 |
| Operand1 = & mut Operand2 | mutable borrow | Operand 1 can read and alter data of another operand2 |

#### Example

The following example shows a shared borrow and mutable borrow:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671410718963/ju7vVHsa1.png align="center")

```rust
fn main() {
    let x = 10;
    let mut y = 13;
    //immutable reference to a variable
    let a = &x;
    println!("Value of a:{}", a); 
    println!("Value of x:{}", x); // x value remains the same since it is immutably borrowed
    //mutable reference to a variable
    let b = &mut y;
    println!("Value of b:{}", b);
    println!("Value of y:{}", y); // y value is changed since it is mutably borrowed
}
```

output:-

```rust
Value of a:10
Value of x:10
Value of b:13
Value of y:13
```

##### Dereferencing Operator

Once you have a mutable reference to a variable, dereferencing is the term used to refer to changing the value of the referenced variable using its address stored in the referring variable.

The following illustration shows that operand 1 mutably borrows the value of operand 2 using & mut and then operand 1 dereferences the value of operand 2 using the `*` operator:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671410773171/kFtwoa6rG.png align="center")

#### Type

The following table shows the dereferencing operator `*` along with its function .

| operator | operation | explanation |
| --- | --- | --- |
| \*Operand1 = Operand2 | Dereferencing a value | point to the value of a mutable borrow variable and can also |

update that variable value |

#### Example

The following example shows how to dereference a variable:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671410815384/kZn2AYc00.png align="center")

```rust

fn main() {
    //mutable reference to a variable
    let mut x = 10;
    println!("Value of x:{}", x);
    let a = & mut x;
    println!("Value of a:{}", a);
    //dereference a variable
    *a = 11;
    println!("Value of a:{}", a);
    println!("Value of x:{}", x); // Note that value of x is updated
}
```

output:

```rust
Value of x:10
Value of a:10
Value of a:11
Value of x:11
```

#### Precedence and Associativity

#### Precedence

The precedence of an operator determines which operation is performed first in an expression with more than one operators.

Operators are listed below in the order of their precedence from highest to lowest :

*   Unary
    
    *   Logical/Bitwise NOT - `!`
        
    *   Dereference - `*`
        
    *   Borrow - `&`, `&mut`
        
*   Binary
    
    *   Typecast - `as`
        
    *   Multiplication- `*`, Division - `/`, Remainder- `%`
        
    *   Addition - `+`, Subtraction - `-`
        
    *   Left Shift - `<<`, Right Shift - `>>`
        
    *   Bitwise AND - `&`
        
    *   Bitwise XOR - `^`
        
    *   Bitwise OR - `|`
        
    *   Comparison - `==` `!=` `<`` >` `<= ``>=`
        
    *   Logical AND - `&&`
        
    *   Logical OR - `||`
        
    *   Range - `start .. stop`
        
    *   Assignment/Compound Assignment - `= += -= *= /= %= &= |= ^= <<= >>=`
        

Note: The operators that are written in the same row have the same order of precedence.  
Associativity

If two or more operators of the same precedence appear in a statement, then which operator will be evaluated first is defined by the associativity.

#### Left to Right Associativity

Left associativity occurs when an expression is evaluated from left to right. An expression such as `a ~ b ~ c`, in this case, would be interpreted as `(a ~ b) ~ c` where `~` can be any operator. The operators below can be chained as left associative.

📝The comparison, assignment, and the range operator cannot be chained at all.

#### Example 1

The example below solves an expression according to its operator precedence:

```rust
fn main() {
    println!("Answer : {}",( 3 + 5 ) * 9 / 7 & 8);
}
```

output:-

```rust
Answer : 8
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671411618510/FdK0k3LWm.png align="center")

#### Example 2

The example below solves an expression according to its operator precedence:

```rust
fn test() {
    println!("{}", 2 + 3 / 5 ^ 7 & 8 | 9);
}
```

output:

```rust
11
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671411629093/EC4hdPaaM.png align="center")

#### If Expression

There can be multiple conditional constructs using an if statement.

*   If expression
    
*   If…else expression
    
*   If…else if…else expression
    
*   Nested if expression
    
*   Shorthand if expression
    

Let’s discuss each one of them in detail:-

#### If Expression

If expression takes a condition. If the condition within the if expression evaluates to be true, then the block of code is executed.

*   Syntax The general syntax is:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671411997109/9PNpXfoME.png align="center")
    
    #### llustration
    
    The following flow chart explains the concept of an if statement:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671412145355/QfuTfgQ2D.png align="center")
    
    ```rust
    fn main() {
          //define a variable  
          let learn_language = "Rust";
          // if construct 
          if learn_language == "Rust" { 
             println!("You are learning Rust language!");
          }
    }
    ```
    
    output
    
    ```rust
    Your are learning Rust langauage!
    ```
    
    #### If…else Expression
    
    In an `if..else` construct, if the condition within the if expression evaluates to be false, then the statement within the else block is executed.
    
    *   Syntax
        
    
    The general syntax is:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671412484707/sFpgHU3Z4.png align="center")
    
    #### llustration
    
    The following flow chart explains the concept of an if..else if..else expression:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671412302685/Nzg-CBSL-.png align="center")
    

```rust
fn main() {
    //define a variable 
    let learn_language = "Rust";
    // if else construct 
    if learn_language == "Rust" { 
        println!("You are learning Rust language!");
    }
    else {
      println!("You are learning some other language!");
    } 
}
```

Output

```rust
You are learning Rust language!
```

#### if…else if…else Expression

If there are multiple conditions to be checked, then if..else if..else construct is used.

Syntax The general syntax is:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671414480483/126nn9979.png align="center")

#### llustration

The following flow chart explains the concept of an if..else if..else expression:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671414512575/Luatxjb1i.png align="center")

```rust
fn main() {
      //define a variable 
      let learn_language="Rust";
      // if..elseif..else construct 
      if learn_language == "Rust" { 
         println!("You are learning Rust language!");
      }
      else if learn_language == "Java" { 
         println!("You are learning Java language!");
      }
      else {
         println!("You are learning some other language!");
      } 
}
```

Output

```rust
You are learning Rust language!
```

##### Nested if Expression

An if expression inside the body of another if expression is referred to as a nested if expression.

*   Syntax An if construct is enclosed within an if construct. The general syntax is:
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671417940483/wyOVdR4x1.png align="center")

Note: The nested if expression can also be written with a AND expression in an if.

```rust
if condition1 && condition2 
{
 //statement
}
```

This is true only if the second if statement is the only thing inside the first if.

#### illustration

The following flow chart explains the concept of a nested if statement .

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671418155672/JTh199FAq.png align="center")

Note: There can be as many levels of nesting as you want.

```rust
fn main() {
    //define a variable 
    let learn_language1 = "Rust";
    let learn_language2 = "Java";
    // outer if statement
    if learn_language1 == "Rust" {  // inner if statement
        if learn_language2 == "Java"{
              println!("You are learning Rust and Java language!");
        }
    }
    else {
      println!("You are learning some other language!");
    } 
}
```

output:-

```rust
You are learning Rust and Java languages
```

#### Shorthand if

Instead of writing a lengthy if-else construct, we can use a shorthand if.

Syntax The general syntax is:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671418234476/ZpUX3WKzO.png align="center")

Note: This is similar to a ternary operator in languages like C and C++.

```rust
fn main() {
   //define a variable  
   let learn_language = "Rust";
   // short hand construct
   let res= if learn_language == "Rust" {"You are learning Rust language!"} else {"You are learning some other language!"};
   println!("{}", res);
}
```

Note: Expressions can return a value, unlike statements. Recall that the semicolon turns any expression into a statement. It throws away its value and returns a unit () instead.

```rust
fn main() {
    let x = "Rust";

    let y: bool = if x == "Rust" { true } else { false };

    // let z: bool = if x == "Rust" { true; } else { false; };

    println!("x:{}", x);
    println!("y:{}", y);
```

Note: Uncommenting line 6 in the above code gives an error ❌ since we are trying to convert an expression to a statement and hence not returning a value.

##### If Let Expression

##### What Is an if let Expression?

if let is a conditional expression that allows pattern matching. The block of code in the construct executes if the pattern in the condition matches with that of scrutinee expression.

*   Syntax The if let expression begins with an if followed by a let and then a pattern having values enclosed within round brackets. Then an equal to `(=)` followed by a scrutinee expression. Then there is a block of code enclosed within `braces{}`.Then there is also an optional else block after this.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671418406378/th4grWzFz.png align="center")

Note: When it says matching of pattern, it means that the defined pattern has the same number of values as that of the scrutinee expression.

#### Examples

The following examples show how the different cases of if let expression can work:

```rust
fn main() {
    // define a scrutinee expression    
    let course = ("Rustlabs", "beginner","course");
    // pattern matches with the scrutinee expression
    if let ("Rustlabs", "beginner","course") = course {
        println!("Wrote all values in pattern to be matched with the scrutinee expression");
    } else {
        // do not execute this block
        println!("Value unmatched");
    }
}
```

output:-

```rust
Wrote all values in pattern to be matched with the scrutinee expression
```

If the first value or second value matches, it can guess the third value.

```rust

fn main() {
    // define a scrutinee expression    
    let course = ("Rustlab", "beginner","course");
    // pattern matches with the scrutinee expression
    if let ("Rustlab", "beginner", c) = course {
        println!("Wrote first two values in pattern to be matched with the scrutinee expression : {}", c);
    } 
    else {
        // do not execute this block
        println!("Value unmatched");
    }
}
```

output :

```rust
Wrote first two values in pattern to be matched with the scrutinee expression : course
```

If the first value matches, it can guess the other two values.

```rust
fn main() {
   // define a scrutinee expression     
   let course = ("Rustlabs", "beginner","course");
   // pattern matches with the scrutinee expression
   if let ("Rustlabs", c, d) = course {
       println!("Wrote one value in pattern to be matched with the scrutinee expression.Guessed values: {}, {}",c,d);
   } else {
       // do not execute this block
       println!("Value unmatched");
   }
}
```

output:-

```rust
Wrote one value in pattern to be matched with the scrutinee expression.Guessed values: beginner, course
```

##### Case 2: When the Pattern is Not Matched

In the example below, the defined pattern does not match with the scrutinee expression so the statement in the else block gets executed.

```rust
fn main() {
    // define a scrutinee expression     
    let course = ("Rust", "beginner");
    // pattern does not match with the scrutinee expression
    if let ("Java", c) = course {
        println!("Course is {}", c);
    } else {
        // execute this block
        println!("Value unmatched");
    }
}
```

output:-

```rust
Value unmatched
```

#### Case 3: When the Pattern is Replaced With `_`

In the example below, the pattern is not defined. Rather it is replaced with an `_`. In this case, the statement within the if let block executes.

Note: A warning, ⚠️, is generated by the compiler because the Rust compiler complains that it doesn’t make sense to use `if let` with an irrefutable pattern.

```rust

fn main() {
    // no pattern is define
    if let _ = 10 {
        println!("irrefutable if-let pattern is always executed");
    }
}
```

output:-

```rust
irrefutable if-let pattern is always executed
```

```rust
warning: irrefutable if-let pattern
 --> main.rs:3:5
  |
3 | /     if let _ = 10 {
4 | |         println!("irrefutable if-let pattern is always executed");
5 | |     }
  | |_____^
  |
  = note: `#[warn(irrefutable_let_patterns)]` on by default
```

#### Match Expression

#### What Is a match Expression?

Match expression checks if the current value corresponds to any value within the list of values. Match expressions are similar to switch statements in languages like C and C++. They give a more compact code when compared with the if/else construct.

*   Syntax Match expression uses a matching keyword. The match expression can be written in two different ways, which are given below:
    
*   Method 1: If you do not want to assign a value to the result variable from within the match block
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671418573041/awnLW8Zcp.png align="center")
    
    ```rust
    fn main() {
        // define a variable 
        let x = 5;
        // define match expression
        match x {
            1 => println!("Java"),
            2 => println!("Python"),
            3 => println!("C++"),
            4 => println!("C#"),
            5 => println!("Rust"),
            6 => println!("Kotlin"),
            _ => println!("Some other value"),
        };
    }
    ```
    
    output:-
    
    ```rust
    Rust
    ```
    
    #### Method 2:
    
    If you want to assign a value to the result variable from within the match block
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671418642159/Fb3osVK3L.png align="center")

```rust
fn main(){
   // define a variable
   let course = "Rust";
   // return value of match expression in a variable
   let found_course = match course {
      "Rust" => "Rust",
      "Java" => "Java",
      "C++" => "C Plus Plus",
      "C#" => "C Sharp",
      _ => "Unknown Language"
   };
   println!("Course name : {}",found_course);
}
```

output:-

```rust
Course name : Rust
```

##### Comparison of The Different Conditional Constructs

##### Use `if` Statement

*   Use an if statement if:
    
    *   It is desired to test the truthiness of an expression
        
    *   There is a single affirmative test
        
    *   There is a need to evaluate different expressions for each branch
        
    *   It can test expressions based on ranges of values or conditions
        

#### Use `match` Statement

*   Use a `match` statement if:
    
    *   It is desired to compare multiple possible conditions of an expression
        
    *   The values belong to the same domain
        
    *   It can test expressions based on values only, i.e., condition cannot take ranges
        

#### Use `if let` Statement

*   Use an if let statement if:
    
    *   There is a pattern in the condition and it is to be matched with the scrutinee expression
        

#### What Is a Loop?

Loops are used to iterate until a defined condition is reached.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671418805037/b7uF08GT-.png align="center")

#### Types of Loops

There are two types of loops in Rust:

*   Definite Loops :- Loops in which the number of iterations is known at compile time.
    
*   Example
    
    *   for
        
*   Indefinite Loops :- Loops in which the number of iterations is not known at compile time.
    
*   Example
    
    *   while
        
    *   loop
        

#### Definite Loop - For Loop

#### What Is a for Loop?

A for loop is a definite loop, meaning, the number of iterations is defined.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671419294544/Wr12MuG98.png align="center")

#### Syntax

The for loop is followed by a variable that iterates over a list of values. The general syntax is :

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671419315353/aZ4e6ix0x.png align="center")

# Example

The following example uses a for loop that prints 5 numbers.

```rust
fn main() {
    //define a for loop 
    for i in 0..5 {
      println!("{}", i);
    }
}
```

output

```rust
0
1
2
3
4
```

*   **An explanation**
    
    for loop definition
    
    *   On line 3 a for loop is defined.
        
        *   Variable i is an iterator variable that iterates over the range with the lower bound as 0 and the upper bound as 5. From here the body of the loop starts.
            
*   for loop body
    
    *   The body of the for loop is defined from line 3 to line 5
        
    *   In each iteration:
        
        *   On line 4, the value of the variable i is printed.
            
        *   The value of the variable i is incremented by 1.
            
*   The iterator variable i traverses over the range until the upper bound is reached.
    

Note: The lower bound is inclusive and the upper bound is exclusive in the range

The following illustration explains this concept:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671419374575/tL0Zujf0C.png align="center")

#### Enumerate

To count how many times the loop has already executed, use the .enumerate() function.

*   Syntax The general syntax is :
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671419435451/q9EBPfQTS.png align="center")

*   Example
    

The example below prints the frequency of iterations and the value of variable.

```rust
fn main() {
  for (count, variable) in (7..10).enumerate() {
      println!("count = {}, variable = {}", count, variable);
  }
}
```

output

```rust
count = 0, variable = 7
count = 1, variable = 8
count = 2, variable = 9
```

#### Explanation

*   enumerated for loop definition
    
    *   On line 2 an enumerate for loop is defined.
        
    *   The variable variable iterates over the range with the lower bound as 7 and the upper bound as 10 and a variable count which shows how many times the loop is iterated. From here the body of the loop starts.
        
*   enumerated for loop body
    
    *   On line 3, the value of count and variable is printed and then incremented by 1.
        

#### indefinite Loop - While and Loop

*   While loop
    

While loop also iterates until a specific condition is reached. However, in the case of a while loop, the number of iterations is not known in advance.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671419559561/sebV96IAc.png align="center")

*   Syntax The while keyword is followed by a condition that must be true for the loop to continue iterating and then begins the body of the loop. the general syntax is :
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671419626987/BTTMKZdSi.png align="center")

*   Example
    

The following example makes use of a while loop to print a variable value. The loop terminates when the variable’s value modulus `3` equals `1`

```rust

fn main() {
  let mut var = 1; //define an integer variable
  let mut found = false; // define a boolean variable
  // define a while loop
  while !found {
      var=var+1;
      //print the variable
      println!("{}", var);
      // if the modulus of variable is 1 then found is equal to true
      if var % 3 == 1 {
        found = true; 
      }
      println!("Loop runs");
  }
}
```

output

```rust
2
Loop runs
3
Loop runs
4
Loop runs
```

#### Explanation

*   A mutable variable, var, is defined on line 2.
    
*   A mutable variable, found, is defined on line 3.
    

#### while loop definition

while loop is defined on line 5. while loop is followed by a variable found. found is initially set to false. !found means that the loop will continue to iterate until the value of found evaluates to be true.The loop terminates when found is set to true. From here the body of the while loop starts

#### while loop body

*   The body of the loop is defined from line 5 to line 14.
    
*   In each iteration:
    
    *   The value of the variable var is incremented by 1 on line 6 and then printed on line 8.
        
    *   If the value of the var modulus 3 is equal to 1, then the value of found is set to true else it prints “loop runs” on line 13 and the loop continues.
        

The following illustration traces the execution of the program:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671420058344/JXNS5PM35.png align="center")

#### Loop

If you want the iteration to continue infinitely, then use the loop keyword before the block of code.

*   Syntax
    

The loop keyword is followed by the body of the loop enclosed within curly brackets `{}`. The general syntax is :

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671420103046/HL6bvI-Hj.png align="center")

#### Example

The following example shows how the loop runs infinitely using a loop. Note: The maximum time that is set for the code to run on our platform is 30sec. Since the code below runs more than that, it won’t execute here. However, the code will continue to run indefinitely.

```rust
fn main() {
  //define an integer variable
  let mut var = 1; 
  // define a while loop
  loop {
      var = var + 1;
      println!("{}", var);
  }
}
```

output:

```rust
Loop continues infinite times
```

*   Explanation
    
*   A mutable variable var is defined on line 3.
    
*   loop definition
    
    *   loop is defined on line 5.
        

From here the body of the loop starts

*   loop body
    
    *   The body of the loop is defined from line 5 to line 8.
        
    *   In each iteration, the value of the variable var is incremented by 1 on line 6 and then printed on line 7.
        
    *   The loop continues to iterate infinitely.
        

#### Break Statement

#### What Is a `break` Statement?

The break statement terminates the loop. It is generally placed inside a conditional statement so that the loop terminates if the associated condition is true.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671420314669/51VTxqUBD.png align="center")

Break statement is valid in case of while, for and loop.

#### Using With a for Loop

Below is an example of break expression, using a for loop.

*   The range defined in the for loop is from 0 to 10.
    
*   Within the for loop :
    
    *   The value of `i` is printed
        
    *   When the value of `i` is equal to `5`, the loop terminates
        

```rust
fn main() {
  // define a for loop
  for i in 0..10 {
    println!("i:{}", i);
    if i == 5 {
      break;
    }
  }
}
```

output

```rust
i:0
i:1
i:2
i:3
i:4
i:5
```

#### Using With a while Loop

Below is an example of break expression, using a while loop.

*   A mutable variable i is defined
    
*   A boolean variable found is defined Within the while loop body :
    
    *   The value of i is printed
        
    *   When the value of `i` is equal to `5`, the loop terminates
        

```rust
fn main() {
  let mut i = 1;
  let found = false;
  // define a while loop
  while !found {
    println!("i:{}", i);
    if i == 5 {
      break;
    }
    i = i + 1;    
  }
}
```

output

```rust
i:1
i:2
i:3
i:4
i:5
```

#### Using With a loop

Below is an example of break expression, using a loop.

*   A mutable variable i is defined
    
*   Within the loop body:
    
    *   The value of i is printed
        
    *   When the value of `i` is equal to `4`, the loop terminates
        

The infinite loop is turned into a “manageable” loop.

```rust
fn main() {
 let mut i = 1;
 // define a loop
 loop{
   println!("i:{}", i);
   if i == 5 {
     break;
   }
   i = i + 1;    
 }
}
```

Output

```rust
i:1
i:2
i:3
i:4
i:5
```

Continue Statement

*   What Is a continue Statement?
    

The continue statement, when encountered inside a loop, skips the execution of the rest of the statements in the loop’s body for the current iteration and returns the control to the start of the loop.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671420870307/Q0ajMnS23.png align="center")

#### Using With a for Loop

*   Below is an example of a continue expression, using a for loop.
    
*   The range defined in the for loop is from `0` to `10` with var variable used for iterating over the loop
    
    *   Within the for loop:
        
        *   The value of var is printed
            
        *   When the value of `var` is equal to `4`, the control goes to the start of the loop
            
        *   The loop executes until the upper bound for the defined range is reached
            

```rust
  fn main() {
  // define a for loop
  for var in 0..10 {
     if var == 4 {
        println!("I encoutered a continue statement");
        continue;
      }
      println!("var: {}", var);
      println!("I did not encounter continue statement");
  }
}
```

output:-

```rust
var: 0
I did not encounter continue statement
var: 1
I did not encounter continue statement
var: 2
I did not encounter continue statement
var: 3
I did not encounter continue statement
I encoutered a continue statement
var: 5
I did not encounter continue statement
var: 6
I did not encounter continue statement
var: 7
I did not encounter continue statement
var: 8
I did not encounter continue statement
var: 9
I did not encounter continue statement
```

#### Using With a while Loop

*   Below is an example of continue expression, using a while loop.
    
    *   A mutable variable var is defined
        
    *   A boolean variable found is defined
        
*   Within the while loop body:
    
    *   The value of var is printed
        
    *   When the value of var is equal to `4`, the control goes to the start of the loop.
        
    *   The loop executes until the value of found does not equal true.
        

```rust
fn main() {
    // define an integer variable
    let mut var = 1; 
    // define a boolean variable
    let mut found = false;
    // define a while loop
    while !found {
      var = var + 1;
      println!("{}", var);
      
      if var == 4 {
          println!("I encoutered a continue statement");
          continue;
        }
        println!("I did not encounter continue statement");
        
        if var == 10{
          found = true;
        }
    }
}
```

Output

```rust
2
I did not encounter continue statement
3
I did not encounter continue statement
4
I encoutered a continue statement
5
I did not encounter continue statement
6
I did not encounter continue statement
7
I did not encounter continue statement
8
I did not encounter continue statement
9
I did not encounter continue statement
10
I did not encounter continue statement
```

#### Using With a loop

*   Below is an example of continue expression, using a loop .
    
    *   A mutable variable var is defined
        
    *   A boolean variable found is defined
        
*   Within the loop body:
    
    *   The value of var is printed
        
    *   When the value of var is equal to `4` , the control goes to the start of the loop
        
    *   The loop executes infinitely
        

Note: This code widget will give an error, ❌, due to limitations of our platform but on the local machine, it will run an infinite loop.

```rust
fn main() {
  // define an integer variable
  let mut var = 1; 
  // define a loop
  loop {
    var = var + 1;
    println!("{}", var);
    
     if var == 4 {
        println!("I encoutered continue statement");
        continue;
      }
      println!("I did not encounter continue statement");
  }
}
```

#### Nested Loops

*   What Is a Nested Loop? A nested loop is a loop within a loop.
    
*   Syntax Here, a for loop nested inside a for loop. However, any loop can be nested inside any loop. The general syntax is :
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671422158956/GlefHU9IV.png align="center")
    

# Example

The following code prints a multiplication table of 1-5 using a nested for loop.

```rust
fn main() {
 for i in 1..5{ //outer loop
  println!("Multiplication Table of : {}", i);
   for j in 1..5 { // inner loop
       println!("{} * {} = {}", i, j, i * j);
   }
 }
}
```

output

```rust
Multiplication Table of : 1
1 * 1 = 1
1 * 2 = 2
1 * 3 = 3
1 * 4 = 4
Multiplication Table of : 2
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
2 * 4 = 8
Multiplication Table of : 3
3 * 1 = 3
3 * 2 = 6
3 * 3 = 9
3 * 4 = 12
Multiplication Table of : 4
4 * 1 = 4
4 * 2 = 8
4 * 3 = 12
4 * 4 = 16
```

#### Explanation

*   Outer for Loop
    
    *   A for loop is defined on line 2
        
    *   The loop takes i as an iterator that iterates over values from 1 to 5.
        
*   Inner for Loop
    
    *   A for loop is defined on line 4
        
    *   The loop takes j as an iterator that iterates over values from 1 to 5.
        
    *   For each iteration of the outer loop, the inner loop runs four times while printing the product of variables i and j.
        

| i | j | output |
| --- | --- | --- |
| 1 | 1 |  |
| 2 |  |  |
| 3 |  |  |
| 4 | 1 \*1 = 1 |  |
| 1\* 2 = 2 |  |  |
| 1 \*3 = 3 |  |  |
| 1\* 4 = 4 |  |  |
| 2 | 1 |  |
| 2 |  |  |
| 3 |  |  |
| 4 | 2 \*1 = 2 |  |
| 2\* 2 = 4 |  |  |
| 2 \*3 = 6 |  |  |
| 2\* 4 = 8 |  |  |
| 3 | 1 |  |
| 2 |  |  |
| 3 |  |  |
| 4 | 3 \*1 = 3 |  |
| 3\* 2 = 6 |  |  |
| 3 \*3 = 9 |  |  |
| 3\* 4 = 12 |  |  |
| 4 | 1 |  |
| 2 |  |  |
| 3 |  |  |
| 4 | 4 \*1 = 4 |  |
| 4\* 2 = 8 |  |  |
| 4 \*3 = 12 |  |  |
| 4\* 4 = 16 |  |  |

Sometimes, you might need to break the outer loop instead of the inner loop. So how can you specify which loop you are referring to? You can use a loop label.

#### Loop Labels

*   What Is a Loop Label? A loop label assigns an identifier to a loop.
    
*   Syntax Write a label and colon before the loop.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1671424241904/EAoiDYKug.png align="center")

*   Example The code below prints the multiplication table of 1 to 5 except 3. See how specifying a loop label helps you to skip the table of 3.
    

```rust
fn main() {
 'outer:for i in 1..5 { //outer loop
    println!("Muliplication Table : {}", i);
   'inner:for j in 1..5 { // inner loop
        if i == 3 { continue 'outer; } // Continues the loop over `i`.
        if j == 2 { continue 'inner; } // Continues the loop over `j`.
        println!("{} * {} = {}", i, j, i * j);
   }
 }
}
```

output:

```rust
Muliplication Table : 1
1 * 1 = 1
1 * 3 = 3
1 * 4 = 4
Muliplication Table : 2
2 * 1 = 2
2 * 3 = 6
2 * 4 = 8
Muliplication Table : 3
Muliplication Table : 4
4 * 1 = 4
4 * 3 = 12
4 * 4 = 16
```

#### Explanation

*   Outer for Loop
    
    *   A for loop is defined on line `2`.
        
    *   The loop has a label outer . It takes i as an iterator that iterates over values from `1` to `4`.
        
*   Inner for Loop
    
    *   A for loop is defined on line `3`
        
    *   The loop has a label inner. It takes j as an iterator that iterates over values from `1` to `5`.
        
    *   For each i the inner loop iterate j times and prints the product `i * j`.
        
    *   When the outer loop increments `i` to `3` and the inner loop starts from j = 1, the condition `i == 3` is found to be true and the continue ‘outer statement causes execution to be transferred to the next iteration of the outer loop on line `2`. The variable `i` is incremented to `4` and the execution continues.
        
    *   When the value of j increments to `2`, then the 2nd iteration of the inner loop gets skipped and continue 'inner causes the execution to be transferred to the next iteration of the inner loop on line `4`. The variable j is incremented to `3` and the execution continues.
        

this series will continue with more hand-on labs .
