RUST is an exceptional programming language that stands out in many ways. It excels in memory management and prevents memory leaks. The rust compiler is user-friendly, providing suggestions to correct mistakes. The cargo build system is a joy to use. When all these features come together, it results in a satisfying experience of compiling code that works flawlessly. Rust ensures correctness, making everything right in the world.
However despite its many benefits, I have noticed some peculiarities that set Rust apart from other languages, but not in a good way. As someone who is now very familiar with the language and experienced with other languages too, I have started question whether it deserves its title of the most loved programming language, and what does that even mean at the end of the day?
I love slating Java simply because it’s boring and monotonous to code in, yet it reads well. Rust on the other hand annoys me for a completely different set of reasons. Don’t mistake annoyance for hate, I don’t hate Rust, 75% of the time I am perfectly happy coding in it. It’s just that 25% that irks me. I can tolerate the scattering of “if let this” and “if let that” with the odd match statement thrown in here and there. I also understand the need, from the language’s perspective, to pack values in return structures like Result and Option. But this is where I find Rust to be particularly irksome.
It pains me!
If there is a need to pack there is also a need to unpack. With all this packing and unpacking, I feel like I have encountered some sort of programming equivalent to a Russian doll. Open the doll, and there I find another doll within and then open that and I find another. In Rust, I could unpack some structure A that gives me B, but B has a method that returns a Result that must be unpacked to get C, and C has another method that must be unpacked to get to a value I need. All this unpacking results in untidy hard to read code. Packing is fine here and there but when it is used excessively and everywhere, it is an annoyance.
pub fn file_name_to_string(path_buf: &PathBuf) -> String {
path_buf.file_name().unwrap().to_str().unwrap().to_string()
}
Annoyance number two is the syntax for lifetime notation. The concept behind Rust lifetimes is fairly easy to understand but oftentimes tricky to implement. A basic rundown is that rust variables exist within the program for a given lifetime. In most cases, the compiler automatically handles lifetime allocation. Variable’s lifetimes change when passing the variable from one function/scope to the next. In some cases, the compiler cannot always account for the length of a lifetime. In such cases, it will raise an error. The developer must then manually account for the lifetime within the code.
The syntax for stating lifetimes in code looks like ‘x where x by convention is usually some character identifier. At first glance this does not seem too bad, however, have a look at the following code snippet
fn mutate_and_share<'a>(&'a mut self) -> &'a Self {
&'a *self
}
Supposedly this function returns a mutable version of a structure. Consider that a similar function could look even worse if it had even more lifetimes and other types of signature syntax added to the mix such as traits implementations. All this syntax makes me think about the future maintainability of Rust code and the time it will take developers to decipher such functions.
The next annoyance comes from third-party Crates. Crates would be libraries or modules in other languages. Rust’s crate problem shares many similarities to other open-source package managers, in that there are often too many solutions doing the same thing. Want an HTTP web server, well there are several to choose from and they all do very pretty much the same thing but all lack something. Which one is the best, most used and most stable… who knows? Are most well documented? Hell no.
To give an example of my own experience. I wanted to use a Sqlite crate in one of my projects. I managed to work with it, but it took me some time to figure it out. This was because the documentation was completely lacking. My first assumption was that this Sqlite crate acted as an interface for a pre-installed sqlite runtime. Yet, it turned out the crate included the sqlite runtime and added it the program at compile time, so all the developer has to do is point to the file that contained the database. The fact remains, clearer documentation would have saved me and likely others some time. I must give the sqlite crate some credit because it at least provided some examples, which aided me in figuring out how to use it. Compared to those crates I have found without any examples or documentation.
Sparks of joy?
So if this is the world’s most beloved programming language. Well for some maybe, but I at least wouldn’t consider it to be my most love language. I can’t help but think back to the Marie Kondo and that meme, “This one sparks joy, this one does not spark joy” and I have to admit I do not feel the spark of joy from coding in Rust until I build a project.