Rust : Concepts That We Should Know

Introduction to the basic concepts of Rust : mutability, shadowing and constant variables.

Digital Delivery
-
6 min
Digital Delivery
/
Rust : Concepts That We Should Know

Rust is a language created by an employee at Mozilla before 2010. After this date, the language was sponsored by the company. Inspired by C/C++, Rust offers more efficiency as a compiled, strongly typed, safe, and performant language without a garbage collector.

A language empowering everyone to build reliable and efficient software.

-rust-lang.org

Rust is used by multiple big companies like Mozilla, Microsoft, and Dropbox for various applications such as building web servers, command-line interfaces, native desktop applications, web apps using WebAssembly, and even operating systems.

Having a safe, multithreaded language is already great, but Rust takes it further with its high performance. Rust is a systems programming language with a compiler, which is key for having performant programs and safe memory management. Rust also offers productivity due to its package of tooling that includes a package manager, testing, and documentation.

If you're just starting with Rust, you may find it complex and not easy to understand, but the good thing about Rust is that it makes sure you understand the concepts before coding.

In this article, we will cover the basic concepts that differentiate Rust from other languages in order to give an accessible introduction to developers who are trying to start coding with Rust.

How Does Mutability Work?

The principal feature of Rust is that variables are immutable by default. This means that when we give a value to a variable, we can't change it anymore, for example:

If we run this code, it will show an error "cannot assign twice to immutable variable a" because we tried to assign another value to an immutable variable. The compiler is capable of showing us errors at compile time to ensure safe code. However, in some cases, we may need to define a mutable variable. This is possible in Rust by specifying the keyword mut, for example:

Now the compiler will not show an error because we specified that the variable is mutable, so we can change its value.

We've covered how to define variables using the let keyword and how to manipulate them with mut to make them mutable. However, there is another keyword to define variables: const. Using const allows us to declare constants.

You might think that using let without the keyword mut already defines constants that will not change, but there are differences:

  • Constants are always immutable; there is no chance they will become mutable, and we can't use the keyword mut.
  • Constants must have their values determined at compile time; they should not have values that will be calculated at runtime.
  • When we declare constants, we should annotate the type of the value.

Example:

You can notice that the variable has a specific naming convention; it's the convention for naming constants in Rust. u32 is the type of the value that we assigned to the variable SURFACE_LAND.

We should also mention that constants are available in the scope where they were defined for the entire runtime of our program.

What Exactly Is Shadowing?

Before introducing shadowing, let's look at an example:

As we learned, we can't re-assign a value to a variable defined with only let, it must be immutable, so the examples that we have will show error normally, that's the case for Example 2, but Example 1 is different, it's not about re-assigning, it's about declaring a variable with the same name as the last variable. In Rust, we say that the first variable is shadowed by the second one, in other words, the second variable overshadows the first, it means that if we print variable a, we will have the first value multiplied by 2. But it's also about scope, for example:

So, as we can see, a was equal to 4, but after re-declaring it, the first variable was shadowed by the second so it equals 8. Now, after opening another scope, we re-declare the variable, so the third variable will shadow the second, but after closing the scope, we returned to the previous declaration that we had in the parent scope.

In this process, we didn't change the variable, we transformed the value, but the variable itself remains immutable after any transformation that we can perform on the value.

We can also change the type of the value in the transformation if we want, but like we said we should use the keyword let in order to create a new variable but with the same name.

Introduction to Data Types

Data Types in Rust are really different, they have a specific syntax. The first thing that we should know is that Rust is a statically typed, in other words, we should specify the types of all variables at compile time, Rust can also understand the type of a variable based on the value that we assigned to it.

We have here two types of Data Type: Scalar and Compound:

Scalar:

Single value: integers, floating-point numbers, booleans, and characters.

Integers:

In Rust, there are Signed and Unsigned integers. Signed integers can be negative (they can have a sign), unsigned integers are only positive integers so they will never have a sign. Here is a table that illustrates multiple types:

Floating-Point:

Floating-point types are numbers with decimal points, they are always signed, there is no unsigned floating-points, and they have two types: f32, f64 (it's the default type).

Boolean:

In Rust, Boolean Types are true and false. To define a boolean, we use the keyword bool.

Character:

The Character type is a primitive alphabetic type. In Rust, we define char with single quotes, but string literals with double quotes.

Compound Types:

Compound types in Rust represent a group of values inside one type. In Rust, we have two: Tuples and Arrays.

Array:

In Rust, an Array is a group of values that have the same type, and the group itself has a fixed length.

Tuple:

In Rust, a Tuple is like an array, but it can have values with different types.

How Functions work in Rust?

Functions in Rust are defined with the keyword fn, the main function is the entry point of our program:

In this example, x * 3 does not have a semicolon, so Rust will see it as an expression that will return a value. If we add a semicolon at the end of the line, we will get an error:

Conclusion

In this article, we had a global view of why using Rust is great. We took a look at the syntax and some basic concepts like mutability, and how Rust offers us a high level of safety and performance. In the coming articles, we will deep dive into some advanced concepts like Ownership.

Published on
April 6, 2023

Industry insights you won’t delete. Delivered to your inbox weekly.

Other posts