Rust claims to run blazingly fast, prevents segfaults, and guarantees thread safety. Katarzyna Macias provides an introduction for a C++ developer.
I decided to learn a new modern language – the more exotic the better. But to be honest, it’s not hard to impress me because throughout my studies and career I have only had contact with the most mainstream languages, like C, C++, Java, Python and Javascript.
At first, I planned to choose between Haskell, Clojure and Scala, but then I made a Twitter survey and I got several recommendations to try Rust. After a quick look at some examples … it looks weird enough. I’ll take it!
I liked it at first sight: Rust may be the language that the world was waiting for! (Yes, I know – it is too early for me to have this much enthusiasm).
The documentation says:
Rust is a systems programming language focused on three goals: safety, speed, and concurrency. It maintains these goals without having a garbage collector.
Looks great: it doesn’t have a garbage collector and that gives it a big advantage over the languages that do have GC. It also introduces a new level of safety. It has a lot of other assets that I don’t know about yet.
I don’t think it will replace C++, because I don’t think that any language will be able to do that within 10–20 years (don’t blame me if I’m wrong). However, it may well become a proud neighbour of C++ on the shelf reserved for the most beautiful programming languages.
A first look at Rust
These are the things that caught my attention when I started to learn about Rust.
Variables are immutable
In Rust, every ‘variable’ – which is called a binding – is immutable by default. The binding declaration is shown in the example below. You can’t reassign the value of
x
since
x
is
const
!
fn main () { let x = 5; x = 3; // This won't compile! }
To make a binding mutable, add
mut
keyword:
let mut x = 5
.
This is different from C++, where you need to add the additional word to make a variable immutable. And I think the Rust solution is better. It’s easy to forget or to skip the ‘unnecessary’ keyword out of laziness. Here, forgetting gives you the less-risky default.
I have even heard a rumour that Bjarne (Stroustrup) once said that he would like to have such ‘inverted const logic’ in C++. But did he really say that? I don’t know.
You can’t use an uninitialized binding
Another safety improvement is the fact that you get a compilation error when you try to use an uninitialized binding. I also appreciate this feature. Why would anybody want to use uninitialized variables? It’s an obvious error, so why not stop compilation when it happens?
Formatting correctness checked at compile time
The next protection for the careless developer: if you’ve ever had a crash in your application because you used the wrong number of arguments in your print function, you will value this. I have had this kind of problem and it was really hard to detect all the places in the code where the print was misformatted (our compiler gave no warnings for that – GCC fortunately does). To make it worse, the crashes were only sporadic. I would really prefer that the code would not compile as soon as the problem was introduced. And so it is in Rust: it won’t allow you to compile incorrect formatting.
fn main () { // This won't compile! println!("The value is: {}"); }
Function declaration order does not matter
You can call functions before you declare them. This code is correct:
fn main () { print_number(5); } fn print_number(x: i32) { println!("x is: {}", x); }
This goes against the expectations of a C++ developer, but perhaps that is not important.
Returning without a return statement
This one is weird. The example below shows how to return a value from a function:
fn add_one(x: i32) -> i32 { x + 1 }
No semicolon, no
return
keyword… And a strange-looking arrow. It doesn’t look very friendly at first sight.
If you want to ask how to return early… Good question. Here you should use
return
:
fn foo(x: i32) -> i32 { return x; // we never run this code! x + 1 }
Further, from the Rust book, we learn that:
Using a return as the last line of function works, but is considered poor style.
Hmm. For me this syntax is odd, but I won’t be discouraged by that.
My impressions of Rust
I feel very positive about Rust and I consider the additional safety as a great feature. I think the more checks that are done during the compilation time the better, as long as the compilation time doesn’t exceed reasonable limits. Remember that the time you spend on waiting for your compilation may save you long hours of debugging.
I feel very curious about the possibilities for this language and I’m excited to learn more!