Rust1 is a relatively new systems programming language (it first appeared in 2010). It is primarily focused on performance and safety; in fact it can be *faster* than C/C++*. While it is syntactically similar to C/C++, the compiler provides many guarantees that prevent a large class of bugs that are very easy to introduce in traditional systems programming languages. However, what this means is that for programmers who come from languages like C/C++, it takes some time to change their mental model; a lot of time in the beginning is spent dealing with the errors the compiler will complain about.
To go into a bit more detail, one of Rust's most unique features is its notion of Ownership. First of all, by default, all variables are immutable. This means that if you try to assign another value to that variable, the compiler will complain. In order to make a variable mutable, you have to explicitly add the
mut keyword. Secondly, by default (except for the primitive types), assigning a variable the value of another variable follows
move semantics. This means that the once the variable on the left side of the
= operator has been assigned the value of the variable on the right side, the latter becomes invalid; attempting to use it will cause the compiler to complain. Thirdly, when it comes to references (which are essentially non NULL pointers), you are allowed to have many immutable references to the same memory location, but only one mutable reference. Finally, when a variable goes out of scope, its value gets dropped (the variable gets destructed).
What does this mean? It means that Ownership follows a set of rules2:
- Each value in Rust has a variable that’s called its owner.
- There can only be one owner at a time.
- When the owner goes out of scope, the value will be dropped.
When you get a reference to a value, it is considered a "borrow
". The Rust compiler has a Borrow Checker; learning to write code that makes the Borrow Checker happy is the biggest hurdle to overcome when learning Rust. For example, if you have a variable that you want to pass to a function, and you pass it by value, when you return from that function, that variable is now invalid; trying to use it will result in the compiler complaining. In languages such as C/C++, this behaviour is perfectly allowed - if the value you passed in was a struct and the function was supposed to populate the fields of the struct, then this would be one of those bugs that are impossible in Rust.
As I'm still currently in the process of learning Rust, I'm not going to try and delve in to all of its features. However, because the language pulls features from a wide variety of languages3 (e.g. such as Enums as algebraic data types, no null value, etc.), it is an incredibly expressive language. As someone who's spent a majority of their programming life (short though it may be) using C/C++, learning rust has been surprisingly therapeutic. It is an incredibly beautiful language, one where the developer is forced to think about their code carefully.
As more time goes by, I'm starting to recognize that the way I was taught programming in computer engineering does not yield good programmers; it yields technical debt. However, I also acknowledge that becoming a good programmer, like anything in life, takes time and effort, and it's unreasonable to gatekeep people who just want to build projects for their own pleasure. That is why I believe Rust is a good common ground to address these two opposing realities. Rust might have a slightly steeper learning curve in the beginning, but it ingrains behaviours that carry over to other languages. I definitely recommend giving it a go; if nothing else, (in my opinion) it's at least a very interesting read.
* Suggested edit by RoboQuote.