DEV Community

Cover image for Learning Rust πŸ¦€: 02- The basics: Variables and Data Types
Fady GA 😎
Fady GA 😎

Posted on • Edited on

Learning Rust πŸ¦€: 02- The basics: Variables and Data Types

In this article we will dig a little deeper into Rust. We will discuss the basic programming concepts but from Rust perspective. Here you will notice the similarities between Rust and the other languages but we won't delve too deep into Rust's unique traits.

⚠️ Remember!

You can find all the code snippets for this series in its accompanying repo

If you don't want to install Rust locally, you can play with all the code of this series in the official Rust Playground that can be found on its official page. (cargo commands won't run though. But you mostly won't be needing it)
⚠️⚠️ The articles in this series are loosely following the contents of "The Rust Programming Language, 2nd Edition" by Steve Klabnik and Carol Nichols in a way that reflects my understanding from a Python developer's perspective.

⭐ I try to publish a new article every week (maybe more if the Rust gods πŸ™Œ are generous 😁) so stay tuned πŸ˜‰. I'll be posting "new articles updates" on my LinkedIn.

Table of contents

The main function

We saw in the last article that when we create a new project with cargo, a new file called main.rs is created for us in the ./src/ directory and in that file, we have the "main" function:

fn main() {
    println!("Hello, world!");
}
Enter fullscreen mode Exit fullscreen mode

The main.rs file and the main function act as the entry point to our program. Your program won't run unless it has those! As opposed to Python, in which you don't need to define a main function or file.

As we can see, the main function doesn't take any arguments initially and doesn't return anything (actually it returns a unit data type "()" but more on that later).

Variables

Variables in Rust are defined by the let and const keywords (Yes! just like JavaScript πŸ˜‰). They are immutable by default (their values can't be changed once set). Let's test this, create a new project called "basics" in your current directory

cargo new basics
Enter fullscreen mode Exit fullscreen mode

And replace the code in main.rs with the following and run it (remember to run a Rust code, type cargo run):

fn main(){
    let x = 5;  // Variables are immutable by default
    x = 6;      // Error: cannot assign twice to immutable variable `x`
}
Enter fullscreen mode Exit fullscreen mode

This code will error out but I'd like to highlight a very beautiful thing about Rust, its Error display method for the errors stack. It is just amazing! Rust uses colors while displaying errors, shows you where and explains why the error occurred and often provides suggestions to help solve them!

Rust Error

To fix this error, we will have to make our variable x a "mutable variable" by using the mut keyword.

fn main() {
    // let x = 5;   // Variables are immutable by default
    // x = 6;       // Error: cannot assign twice to immutable variable `x`
    let mut x = 5;
    x = 6; // This won't error out as x is mutable now.
    println!("The value of x is {x}")
}
Enter fullscreen mode Exit fullscreen mode

Here we initially set x to 5 and used the mut keyword to tell our program that this variable is mutable then we changed its value to 6 and used the println! macro to print its value in stdout (Rust uses curly-braces "{}" for string interpolation in the println! macro). You should see the following printed on your screen (ignore any warnings that appears for now).

The value of x is 6
Enter fullscreen mode Exit fullscreen mode

The const keyword is the other method to define variables in Rust except they are always immutable. Constants can be declared in the global scope and must be a known value/calculation at compile time (can't be calculated at runtime)

const MINUTES_IN_DAY: u32 = 1 * 24 * 60;      // Valid
const WORK_HOURS_PER_WEEK = user_input;  // Invalid
Enter fullscreen mode Exit fullscreen mode

(u32 is the data type of the constant which stands for "unsigned" 32 bits integer)

Data Types

Rust is a statically typed language, which means that it must know the types of all variables at compile time. The Rust compiler does a good job at inferring them. But when it can't, it's the programmer's job to declare the variables type. Take a look at this example:

let guess = "42".parse().expect("Not a number"); // Error: type annotations needed
Enter fullscreen mode Exit fullscreen mode

This statement will fail despite that "42" is an integer! that's because Rust has several integer types the compiler needs to know which one you mean.
Broadly, Rust has two main categories for its data types:

  • Scalar: Represents a single value.
  • Compound: Represents a group of multiple values.

Scalar Data Types

Integer Types

Like Python and the other languages, an integer is a whole number without a fractional component. In Rust, the integer type is written as follows:

[i/u][size in bits]

Where "i" is a signed number (can hold negative values) and "u" is an unsigned number (only positive values). The size in bits can be 8, 16, 32, 64 and 128 which determines the maximum value that the variable can hold (Integer type defaults to i32).
So, for example:

i8: 8-bit signed integer (from -128 to 127)
u8: 8-bit unsigned integer (from 0 to 255)
Enter fullscreen mode Exit fullscreen mode

There are also the "isize" and "usize" types that depends on the machine architecture that the program runs on (either 32-bit or 64-bit).
Beware that if you use an integer type smaller that you have intended it to be, Integer Overflow may occur!

Floating-Point Types

Like integers, floating-point types are denoted with the letter "f" and they can be a single precision (f32) or a double precision (f64) (the default is f64)

The Boolean Type

Boolean in Rust are either true or false and denoted by the bool keyword. Like in other languages, Boolean type is frequently used in condition checks.

The Character Type

In Rust, the Character type is defined by single quotes "''" and denoted by the char keyword. It holds single character (Unicode is valid)

Compound Types

The Tuple Type

The tuple is Rust as a way to group several values together with different types into one compound type. It has a fixed size and can't grow or shrink. Like in Python, it's a comma-separated list of values

let ip_address: (u8, u8, u8, u8) = (168, 1, 1, 10);
let user: (&str, u8, char, bool) = ("Fady", 37, 'm', true);
Enter fullscreen mode Exit fullscreen mode

To get the values for a Tuple, you can use pattern matching to "destruct" the tuple

let (a, b, c, d) = ip_address;
println!("The IP address is {a}.{b}.{c}.{d}")
Enter fullscreen mode Exit fullscreen mode

Or you can access the tuple elements by using a period (.) followed by the index of value (zero indexed)

println!("The IP address is {}.{}.{}.{}", ip_address.0, ip_address.1, ip_address.2, ip_address.3)
Enter fullscreen mode Exit fullscreen mode

A Tuple without any values has a special name, unit (remember the return value of the main function?). It is written as () and represents an empty value or an empty return type (like void in C an Java).

The Array Type

Arrays are another way to group together multiple values in a compound type but this time all the values must be of the same type. And like Tuples, Arrays are always of a fixed length. Arrays in Rust are similar to Lists in Python as they use the square brackets [] in its definition and we can access their values by providing the index inside the brackets.

let number = [1, 2, 3, 4];
println!("The second number is {}", number[1])
Enter fullscreen mode Exit fullscreen mode

You can provide the type of an Array like this

[type; size]

let a: [u8; 5] = [1, 3, 4, 5, 6];
Enter fullscreen mode Exit fullscreen mode

Also we can initialize an Array like this

let array = [value; size];

let a = [10; 3]; // An array of size 3 of 10 value
Enter fullscreen mode Exit fullscreen mode

Rust won't let you use indexes past the size-1 of the Array. For example, the following will error out:

let hours = [1; 24];
println!("{}", hours[25])
Enter fullscreen mode Exit fullscreen mode

In the next article, we will continue our discussion about the Rust basics, function and flow control. See you then πŸ‘‹

Top comments (0)