The “new native languages” are popular and always growing. Sure there’s still plenty of love for the standard enterprise languages: C# and Java, but both languages have become bloated over time and come with their own inherent problems. When it comes to writing code with a small footprint that runs as a fast as possible (say, in a serverless architecture like AWS Lambda) having a slow startup, like Java’s Virtual Machine that needs to be booted with each run, or running with a lot of bloat (garbage collectors, branch optimizers, etc.) can be a negative. That and, while C and C++ aren’t going extinct anytime soon, what a programmer looks for in a language has changed over the years. This has led to the creation of three powerful languages that compile down to machine code: Swift, Go, and Rust.
All three languages compile down to machine code and they all take some inspiration from C (like virtually every language that’s been created since), but that’s where the similarities end. In fact, it’s probably not helpful to group these three languages together as they all were created to fulfill a different need, but I see them bundled together in tech blogs and lectures quite often so, here we are.
Rust’s approach is most akin to C compared to the other languages. It’s a low-level, multi-paradigm language that focuses on being lightweight, yet much safer than C when it comes to threads and memory. It implements several modern concepts that programmers take for granted nowadays like templates, dependency management, a build system, and it’s built with concurrency in mind. These are all solid selling points for me. The syntax is familiar and it didn’t take me any time to follow some simple procedural code.
Now for the weirdness. I shouldn’t be surprised by weird behavior when it comes to programming languages. After all, I probably write more JavaScript than anything and JS holds the gold medal for obtuse and unexpected behavior. That said, here’s a list of hurdles I’ve had to get over since getting started with Rust:
The Hurdles
No Function Overloading
The first time I tried to write a second signature for one of my functions I was dumbfounded. “The name my_function
is defined multiple times”. How could it possibly not allow for function overloading? But it doesn’t. There is a more language-specific methodology for accomplishing this using Traits
and – after doing some research – I now understand why Rust doesn’t offer function overloading, but it’s definitely going to take some getting used to. Naming is always one of the hardest tasks a programmer faces, and now I need to name more.
Crates Galore
Given that Rust is designed to be lean (“you don’t pay for what you don’t use”) you end up importing a lot of crates right away. I for example wanted to read files, parse XML, send HTTP requests, and parse and build JSON. You’d need to import quite a few things to accomplish these tasks in any language. But with Rust, give it’s community nature, I spent a long time trying out different crates. Take HTTP requests for example. There is a std::net
crate for networking tasks, but it’s supremely low-level. A lot of resources pointed more towards hyper
and that works like a charm unless you want to make requests over HTTPS instead, in which case you to dig for an SSL crate or rely on a variant that is tied to an SSL implementation like hyper_openssl
.
In the end I opted for reqwest
based more on its documentation and examples than anything else.
String
vs str
This one isn’t anything I haven’t dealt with before, but it’s been literally years since I’ve worked in a language that defaults to fixed-length character arrays as opposed to string objects. For most applications I can think of, you really want String
for the ability to append, split, join, get substrings, etc. but Rust actively wants you to use str
.
The Nice Parts
No Exceptions
This might sound like a negative, but the way Rust handles errors is actually quite elegant. Rust also doesn’t have a concept of null
in an attempt to avoid the Billion Dollar Mistake. It’s strange to think about Result
and Option
but I think, in the long term, I’m going to love that the language is designed this way.
The Compiler
I ran into a lot of compile errors. I mean, a lot of compile errors. But I never felt misguided or lost by them. The exact part of the code that was an issue was always highlighted and it always provided a The compiler will even recommend ways to fix code
The Speed and Footprint
As I said up above, Rust is built to be a C replacement for systems programming so it is blazing fast and the programs are tiny. Rust would be perfect for Arduinos and embedded systems, but at the same time, the Rust Handbook (which I have not completed) pushes you towards making a multi-threaded web server so it’s very utilitarian.
Check out my GitHub if you want see what kinds of things I’m building with Rust. I’ll be uploading projects there.