Introduction to Common Programming Concepts in Rust
Tags: rust, javascript, beginners, programming
Published: 2023-07-21 04:52:47

In this article, we'll explore some fundamental programming concepts present in Rust, such as variables, conditions, and basic types. To make the most out of this article, it's recommended to have some prior experience with at least one programming language like Python, JavaScript, or Java.

## What is Rust
Rust is a statically typed programming language designed for performance and safety. Originally developed at Mozilla, it caters to system-level programmers who work with low-level byte tweaking code. You can learn more about the history of Rust [here](https://en.wikipedia.org/wiki/Rust_(programming_language)). 

## Installation 

As this article primarily focuses on teaching programming concepts, we won't delve deep into installation. If you wish to install Rust globally on your computer, you can follow the instructions [here](https://www.rust-lang.org/tools/install). Alternatively, you can code along with the article using the [Rust Playground app](https://play.rust-lang.org/).

Let's dive right in and start exploring Rust!

### Variables 

Declaring variables in Rust is straightforward. We use the `let` keyword to do so.

```rust
   let even_number = 2;
```

This is similar to the `let` keyword in JavaScript, but Rust treats it differently. By default, variables in Rust are immutable, meaning you can't change the value assigned to a variable.

![code representing rust variable declaration without mut keyword](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/56kdwg5c9nyue2pnf3iy.png)

As shown above, our code fails because we are unable to change the value of our variable `even_number`. To change the value of a variable, we must add the `mut` keyword, which stands for "mutate." 

```rust
 let mut even_number = 2;
```

![code representing rust variable declaration with mut keyword](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jygxun39hhpsfnttynd1.png)

Now, our code runs fine and prints an output (Note: ignore the warning signs for now, they only indicate that we haven't used the `even_number` variable).

A variable in Rust can only have one type, which can either be explicitly assigned or inferred by the Rust compiler. Unlike JavaScript, once a type is assigned to a variable in Rust, it cannot be changed.

```rust
 let mut even_number = 2;
// This will not compile
 even_number = true;
```

![image showing we can change variable types in rust](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7uqphx3dn6rwvv5ve7bg.png)

As seen above, the Rust compiler throws an error for "mismatched types." It expects the `even_number` variable to always be an integer but got a boolean type.

## Basic Types 

### Boolean 
A Boolean type is a type that can have only two values: true or false. To declare a boolean in Rust, we use the `bool` keyword.

```rust
let is_valid: bool = true; 
```
By default, variables declared as bool are automatically set to false.
 
```rust
let is_updated: bool; // will be false 
```
Boolean types are mainly used in conditionals, such as if and else statements, where you can check if a variable is true and proceed accordingly. 

### Integers
Integers in Rust are numbers without decimal points. There are two types of integers in Rust: `signed` and `unsigned` integers.

#### Signed Integers 
Signed integers can be positive or negative. Examples include: 20, -20, 34, -34, etc. Signed integers are represented by adding an `i` at the start of the integer range.
 
```rust
  let count: i64 = 1501
```

#### Unsigned Integers 
Unsigned integers are only positive integers. Examples include: 20, 34, 42, 382728289, etc. Unsigned integers are represented by adding a `u` at the start of the integer range.

```rust
  let age: u8 = 54
```
The integer type specifies the length of data that the variable can hold. 

#### For Signed:
| Length  | Signed | Range |
| ------  | ------ | ---- |
| 8-bit  | i8  | -128 to 127   | 
| 16-bit | i16 |  -32,768 to 32,767  |
| 32-bit | i32 |  -2.147e9 to 2.147e9  |
| 64-bit | i64 |  -9.223e18 to 9.223e18  |
| 128-bit | i28 |  -1.701e38 to 1.701e38  |

#### For Unsigned:

| Length  | UnSigned | Range |
| ------  | ------ | ---- |
| 8-bit  | u8  | 0 to 255   | 
| 16-bit | u16 | 0 to 65,535  |
| 32-bit | u32 | 0 to 4.295e9  |
| 64-bit | u64 | 0 to 1.844e19  |
| 128-bit | u28 | 0 to 3.403e38  |

If we use an integer type and assign a value below or above the range of that type, Rust will panic.

Example: 

```rust 
   // this will not compile 
   let counter: i8 = 128;
``` 

### Floats 
Floats are numbers with decimal points. All float types in Rust are signed. There are two types of floats in Rust: `f32` and `f64`.

Example:

```rust 
   let amount: f32 = 20.50; 
```

### Character
This type is similar to character in other programming languages and is represented with the char keyword.

Example: 

```rust 
  let alphabet: char = 'a';
```

Notice that the value of the `char` type must be enclosed in single quotes.


## Compound Types 

### Arrays
Arrays are used to group data of the same type together. Unlike arrays in JavaScript, Rust arrays are not dynamic. Rust arrays are stored on the stack, so their size and length must be known during initialization.

To declare an array, use the syntax `[type; size]`, where `type` is the type of data to store, and `size` is the number of elements in the array.

Example: 
 
```rust 
   let students_age: [u8; 5] = [10, 12, 9, 11, 10];
```

Values in an array must be of the same type. You can't have a `char` inside an array of numbers like you could in JavaScript.
 
Example: 

![example code showing you can't add multiple types to a single array in Rust](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u7emxf1tzg9htd445pc0.png)

The above example fails because the `char` type was included in the list. 
Notice that we didn't explicitly add the array type because Rust can infer it from the provided data.

#### Accessing and Updating Arrays
Accessing an array element in Rust is similar to other programming languages: we use the element's index. 

Example:

```rust 
fn main() {
   let numbers = [3,2,3,5,7,8,9]; 
   println!("{}", numbers[0]); // 3
   println!("{}", numbers[4]); // 7
}
```

To update or mutate an array, we must use the `mut` keyword.
 
Example:

```rust 
fn main() {
   let mut numbers = [3,2,3,5,7,8,9]; 
   numbers[0] = 1; 
   println!("{:?}", numbers) // [1,2,3,5,7,8,9]; 
}
```
As shown from the above the first number in the array was changed from 3 to 1. 
__NB__: The `:?` is a debug trait, you shouldn't worry about that now but you will need to include that to display the array of numbers. 

### Vectors 
Vectors are similar to arrays but are dynamic, meaning their sizes can change. They are stored on the heap rather than the stack. To represent a vector type, use `Vec<T>` and initialize it with `vec![...]`. 

Example: 

```rust 
   let counter: Vec<i8> = vec![4, -5, 7]; 
```
From the above we declare a vector of type `i8` with three values. 

We can also declare a vector with zero initial values using: `Vec::new()`

Example: 

```rust 
   let mut current_counts: Vec<i8> = Vec::new();
   println!("{:?}", current_counts); // []
```

To add more values to a vector, use the `.push` method. 

Example 

```rust 
  let mut current_counts: Vec<i8> = Vec::new();
   current_counts.push(5);
   println!("{:?}", current_counts) // [5]
```

To remove items from the vector, use the `.pop` method.

Example: 

```rust 
   let mut counter: Vec<i8> = vec![4, -5, 7]; 
   counter.pop(); 
   counter.pop(); 
   println!("{:?}", counter) // [4]
``` 
From the above we call the pop method twice which removed two elements from the vector. 

Also just link arrays we also use the index of elements to access those elements in the vector. 

Example: 

```rust 
   let counter: Vec<i8> = vec![4, -5, 7]; 
   println!("{}", counter[1] ); // -5
```

## Conditions
Rust conditionals work similarly to other programming languages. To conditionally run a block of code, use the `if else` expression. 

Example

```rust 
fn main() {
   let count = 2;
    if count > 2 {
        println!("Count is greater than 2");
    } else {
        println!("Count is less than 2");
    }
}
```

The conditions must always evaluate to a bool type. The code below will not compile:

```rust 
   let count = 2;
   // This will fail 
    if count {
        println!("Count is greater than 2");
    } else {
        println!("Count is less than 2");
    }
```

`count` is an integer type, not a `bool` type. Unlike JavaScript, Rust does not implicitly typecast. 

## Loops
Rust offers three kinds of loops: `for`, `while`, and `loop`. 

### For loop
The for loop in Rust is similar to `for-in` loops in JavaScript. It is used primarily with arrays and allows you to loop over each element. 

Example: 

```rust 
fn main() {
   let numbers = [3,2,3,5,7,8,9]; 

    for num in numbers {
        println!("the number is: {num}");
    }
}
```

You can also loop over a range with the Rust for loop.

Example: 

```rust 
fn main() {
    for num in 0..10 {
        println!("the number is: {num}");
    }
}
```

### While loop
While loops execute a block of code repeatedly as long as a condition is `true`. The loop breaks when the condition becomes `false`. 

Example: 

```rust 
fn main() {
    let numbers = [3,2,3,5,7,8,9]; 
    let mut cal = 0;
    let mut index = 0;

    while cal <= 20 {
        println!("the current calculated value is: {}", cal);
        cal += numbers[index];
        index += 1;
    }
}
```
From the above the loop will continue to until the variable `cal` is greater than 20 then it stops. 

### loop
The loop executes a block of code infinitely until you manually stop it using the `break` keyword.

Example: 

```rust 
fn main() {
   let mut counter = 0;

    loop {
        counter += 1;
        println!("The counter is currently {counter}");
        if counter == 10 {
           counter = counter * 2;
            break;
        }
    };

    println!("Total counter is {counter}");
}
```

## Function
Declaring a function in Rust is similar to other programming languages. So far, we have seen the `main` function, which serves as the entry point that Rust looks for when running our code.

We can create our own functions with different names and use them in the `main` function. 

```rust 
fn main() {
  let result = addition(20, 20);
  println!("result: {}", result);

 }

 fn addition(num1: i8, num2: i8) -> i8 {
      num1 + num2
 }
```

In the above example, we created a function named `addition` with two arguments, `num1` and `num2`, both of type `i8`, and a return type `-> i8`.

Notice that within the `addition` function, we didn't explicitly add the `return` keyword. This is valid because Rust will implicitly return any line within the function that doesn't end with a semicolon 

## Exercise
Now that we've covered a lot of ground, it's time to test your skills with an exercise:

Write a program that uses println! to print all the numbers from 1 to 100, with two exceptions. For numbers divisible by 3, print "Fizz" instead of the number, and for numbers divisible by 5 (but not 3), print "Buzz" instead. For numbers divisible by both 3 and 5, print "FizzBuzz".

In conclusion, this article provided an introductory overview of common programming concepts in Rust. We explored variables, conditions, basic types, and compound types like arrays and vectors. Additionally, we covered loops, functions, and even challenged ourselves with an exercise to solidify our understanding. Rust's focus on performance and safety makes it an excellent choice for system-level programming and low-level optimizations. As you continue your journey with Rust, remember that practice is key to mastering any programming language. Embrace the power of Rust's expressive syntax and its robust features to build efficient and secure applications. Happy coding!