“The technology of the past comes to save the future of itself. This is how Graydon Hoare, the creator of Rust, describes what he wants to accomplish.
This is one of the key characteristics of Rust: using technologies well known in academia but rarely implemented in contemporary programming languages. Old, reliable and sometimes forgotten technologies. But which, above all, work extremely well.
These technologies are primarily used for one thing: security.
Does it sound boring? This is not the case, if you ask the community. A whopping 87% of Rust developers love this language above all else, making it the most popular language since 2016 according to this year’s StackOverflow Developer Survey.
You would think that software developers are some of the most innovative humans on this planet. Rust, however, is the exact opposite of the “go fast and break things” mantra. Still, Rust developers are almost guaranteed to learn concepts they’ve never heard of before.
From the novelty of systems programming for some developers to algebraic data types to Rust’s own approach to memory security: every developer can find something new and incredibly useful to learn. And there are more reasons to fall in love with Rust.
More memory security without garbage collection
One of the challenges of every programming language is to manage computer memory safely and efficiently. Python, for example, has a garbage collector that constantly searches for memory that is no longer in use and cleans it up while the program is running.
In other languages, like C and C ++, the programmer must explicitly allocate and free memory as they go. Since all memory related issues are therefore resolved before the program is run, this approach is much better for optimizing performance.
On the flip side, memory is yet another thing that developers have to think about all the time. This is one of the reasons it takes a lot longer to write a program in C than in Python, even though it ultimately does the same.
Rust takes another route: memory is allocated through a property system at compile time. This is a neat hack to ensure that unused data is cleaned up without forcing the programmer to think about allocating and freeing memory all the time.
Basically the property is a set of three rules:
- Every value in Rust has a variable called owner.
- There can only be one owner at a time.
- When the owner goes out of scope, the value will be deleted, freeing memory.
A simple example is to assign a vector in Rust:
In the second line, the vector [1, 2, 3] with the owner a is created. After that, b becomes the owner of the vector. Since the correct owner is called in the print statement, this program compiles and returns the expected result when executed:
On the other hand, you can try to call the vector with its previous owner, A, like this:
In this case, the compiler returns an error because has already been deleted in the third line. There’s a lot more depth to the subject, but that’s the basic idea.
In comparison, Python would work in the second case. Its garbage collector would only delete A after the last time it was called, which is good for the developer but not so good in terms of memory space.
In C, things would be a little more complicated: we would have to allocate memory space for a, then point it to the vector, then allocate more memory space for B, point B to A, and finally free the space occupied by A and B when finished.
In this sense, Rust’s approach to memory is a compromise between speed of development and performance. While it’s not as easy to write as Python, it’s not as clunky as C once you understand the concept of ownership.
On the other hand, the efficiency is pretty amazing: Tilde’s developer team, for example, managed to reduce their memory usage by 90% after rewriting some JavaHTTP parts in Rust.
Static input without getting ugly
It’s almost a religious war between fans of dynamic typing and static typing. Although it is much easier to produce software in dynamically-typed languages, the code can become impossible to maintain quite quickly. This is one of the reasons that Python code can be quite difficult to maintain, compared to C for example.
On the other hand, having to declare the type of each C-style variable can get pretty annoying. If you’ve ever tried using a [double] in a function that returns a [float] type C, you know what I mean.
Rust goes halfway: it’s a static type system, but it only requires the programmer to specify higher-level types like function arguments and constants. Inside function bodies, Python type inference is allowed.
A particularly useful characteristic of Rust is that it also has a type of None. This allows you to handle exceptions at compile time so that the program can be assured that it will work properly for the end user. Consider this example, where we can get a person’s full name whether or not they have a middle name:
While versions of the None workaround exist in other languages as well, it does introduce Rust’s ambition in a neat way: not to make things too hard to write while still keeping the code as durable and maintainable as possible.
While Python is a general-purpose programming language, Rust is, like C, decidedly for system programming. While Rust is not the ideal language if you are building an application for your end user, it is perfect for building software that provides services to other software.
A smart approach to system programming
As such, efficiency is at the heart of Rust. This is best demonstrated by zero cost abstractions, which interpret code while minimizing memory usage. As Bjarne Stroustrup, the inventor of C ++, says: “What you don’t use, you don’t pay for. And further: what you use, you could not code better by hand.
For example, consider adding all integers up to 1000 in Python:
That’s 1,000 iterations and additions with each code execution – and you can imagine how much that can slow down the code. In contrast, consider the same in Rust:
It comes down to the constant 499500. This is because memory usage has just been reduced by a factor of 1000.
While these abstractions also exist in C, Rust makes heavy use of them – in fact, one of the goals is to add as many zero-cost abstractions as possible to the language. In that sense, Rust is kind of like the next C level.
C has been around for over 40 years and Rust aims to do the same. Rust places such importance on backward compatibility that you can still run code in Rust 1.0 today. Likewise, if you write Rust code today, you should still be able to run it in twenty years. Rust will not rust!
A small but amazing community
With the emphasis on safety and durability and all its nifty details talking about it, it’s no wonder Dropbox has rewritten much of its basic structure in Rust. Mozilla, Rust’s first major sponsor, wrote vital parts of Firefox there. Microsoft considers C and C ++ no longer secure for critical software and is investing more and more in Rust.
And it’s not just big business – the love for Rust translates into the individual programmer. Even though only five percent of StackOverflow survey respondents use Rust so far, these developers are extremely enthusiastic about the language.
And there are reasons for this. Not only the language specification and the compiler are very well thought out. There is rust to install and manage the tool chains. There’s Cargo, a command line tool that comes with every Rust installation that helps manage dependencies, run tests, and generate documentation.
There is crates.io where users can share and discover libraries, and docs.rs where they are documented. There are Clippy’s compiler lints and rustfmt automatic formatting.
Beyond that, there are official and unofficial chats, subtitles, user forums, StackOverflow questions, and conferences all over the world. With a community that puts usability above all else, is there anything else to ask?
The downside: the need to run before knowing how to walk
The only disheartening thing about Rust is the high start-up cost. While you would need a day or two to be productive in most languages, it is more like a week or two in Rust.
This is due to the many new concepts that other languages do not use and the fact that there are usually a lot of errors at compile time. You have to handle all exceptions from day one, and you can’t just write working code that runs and add exceptions later like you would in Python.
Also, since Rust is still fairly new, not all of the libraries you might want are there yet. Other than the official documentation and various questions about StackOverflow, there aren’t many tutorials either.
The good news is that once you’ve learned the concepts and your program is compiled, it runs like a charm. In addition, it should still work in twenty years due to backward compatibility.
Considering the durability of your code, and the fact that Rust is backed by a number of large companies, a week or two of initial learning might well be worth it, despite the downsides.
The bottom line: hack without fear
Rust is more than safety. But it’s hard to deny that many of its core concepts are aimed at eliminating memory leaks and other security issues. And in an age when software is everything, security is a must.
There is probably a space for every language to come: Go increasingly populates the Python and Java space, Julia is tackling Python in data science, and Rust thrives in Python and C ++. What makes Rust special is its amazing community, innovative features, and the fact that it’s built to work for decades.
There is still a lot of work to be done, and only a fraction of it can and will be done in Rust. New languages today are likely to stay for a while, although other languages will emerge in the next few years as well. But if I had to place my chips on just one language, Rust would be a safe bet.
This article was written by Rhea Moutafis and was originally published on Towards data science. You can read it here.