As part of my summer vacation from work this year, I decided to learn Rust, a programming language that’s been gaining a lot of popularity recently. After using it for a few months I can see why. Rust is a systems-level language designed for things that need to be very efficient and fast. It’s designed to take the place of C, the workhorse of a language that’s been the standard tool for building low level programs for over 40 years. This is no easy task as many languages have tried to take C’s place before and failed. But I think that Rust has a good chance.
The language has a lot of the comfort and ergonomics that I am used to having with TypeScript, but it’s incredibly fast and has something that TypeScript (or really, JavaScript) lacks: a real Enum type. Combined with match statements, this creates a core concept in Rust that makes everything feel very safe.
In my opinion, one of the major problems with many programs is when developers write code that can fail but don’t handle the failure case. With Rust, this is much harder to do. I love that the language encourages good practices while making it relatively painless to do so.
One of the biggest challenges of C is memory management. You can’t just define a variable, you have to allocate memory for it and, crucially, deallocate that memory again when you’re done. This is a fundamental coding problem actually, and every language handles it differently. Many modern languages have a Garbage Collector that attempts to free up resources when they are no longer being used, but such a system requires a lot of overhead and isn’t suitable for systems-level code. Well, Rust has a clever solution: the concept of ownership.
I won’t get into it too deeply but basically if you have a variable with a reference to some data, and you pass that variable to another function, the new function now owns that variable and it cannot be used by the original function anymore. If the new function only needs to read the variable, it doesn’t need ownership and instead it can just borrow the reference. With this rule in place, it’s easy for the compiler to determine when memory needs to be freed and the developer doesn’t have to think much about it. Very elegant.
Finally, Rust has its own package manager and an ecosystem full of great packages (crates) to do whatever you might need.
Anyway, I enjoyed the language so much that I decided to completely rewrite one of my personal projects using Rust: the code searching tool grepdef. Previously it was written in JavaScript, but required leveraging an external searching engine to do its work. Since that engine (the very excellent ripgrep) is written in Rust, I figured I might be able to get the same level of performance by writing the whole thing in Rust instead.
Originally I figured I’d have to rely on the ripgrep library to do the searching, but it turns out that the searching needed by grepdef is actually much simpler than what ripgrep was designed to handle, and so I was able to get comparable performance from a custom algorithm!
I’ve now released grepdef version 3.0, which is a total rewrite in Rust, no longer has the dependencies of node and ripgrep, and even supports Rust as a language to search. Check it out! The CLI arguments are all the same (almost: the version option is slightly different) to make migration easier. See the upgrade steps if you had grepdef installed before. It should work fine out of the box with vim-grepdef or vscode-grepdef.
Photo by Beth Macdonald on Unsplash

Leave a comment