Logo

Why Rust is so difficult to learn?

Rust is not like any other languages. I've been coding in TypeScript and Python for 5 years. On the other hand, I've coded in Rust for only 2 years but I can already tell you which language taught me the most.

From my personal experience, Rust introduces completely new concepts that exist in no other languages and force you to learn everything from scratch, again. Concepts such as ownership, borrowing, and Vecs that we will cover briefly in this essay.

But first, the best way to illustrate my thoughts is probably to show you the same code in Python and Rust.

In the following code, we define a simple User class with a constructor. We also define a method called greet() that greets the current user using its name. Then, we define a print_name() function that display the user's name. And finally, we store users in an array and add a little bit of code to create an instance of the User class and play with it.

Here's the Python code:

class User:
    def __init__(self, name):
        self.name = name
 
    def greet(self):
        return f"Hello, {self.name}"
 
 
def print_name(user):
    # Python passes object references around freely.
    print(user.name)
 
 
users = []
 
name = "Ferris 🦀"        # UTF-8 string
user = User(name)
 
users.append(user)       # list, similar to Rust Vec
print_name(user)         # still usable after append
 
print(user.greet())

And now this is the Rust version:

struct User {
    name: String,
}
 
impl User {
    fn new(name: String) -> Self {
        Self { name }
    }
 
    fn greet(&self) -> String {
        format!("Hello, {}", self.name)
    }
}
 
fn print_name(user: &User) {
    // borrowing: we read the user without taking ownership
    println!("{}", user.name);
}
 
fn main() {
    let mut users: Vec<User> = Vec::new();
 
    let name = String::from("Ferris 🦀"); // UTF-8 string
    let user = User::new(name);           // name is moved into User
 
    print_name(&user);                    // borrow user before moving it
 
    users.push(user);                     // user is moved into the Vec
    // print_name(&user);                 // error: user was moved
 
    println!("{}", users[0].greet());     // access through the Vec
}

Rust's basic concepts

To understand the differences, let's explain basic Rust concepts we used in the code above.

Ownership

In Rust, when we declare a variable, it owns its value.

Borrowing

Borrowing allow to use variables without taking ownership.

Vectors

Vec (short for Vectors) are one of the most important data structure in Rust. Rust make the difference with arrays explict and we'll understand why in this section.

Strings

Finally, String is another data structure in Rust built on top of Vec.

The borrow checker

Rust is a compiled language. Like every compiled language, it has a compiler.

Rust's compiler is rustc which comes pre-installed when you install Rust.