Written on 2024-04-10 by Adam Drake - 7 min read
I have been endeavouring to learn Rust for a while. I am not sure why as there is no immediate need for such a language in my programming life at the moment, but I saw it getting so much love and attention in the community that I thought I should give it a go.
I have tried several courses — building a real app in Rust, Ultimate Rust 2, Rust for TypeScript Developers and I have also discovered the very in-depth content of Jon Gjengset on YouTube (amazing when you have some time to go deep into specific parts of Rust) — and I would say I have a foundational knowledge of Rust.
Throughout the learning experience, I realised I was using JavaScript as my point of reference when learning certain concepts. I do have familiarity with other languages like Python and Java but I feel most comfortable in JavaScript so I default to that when trying to build mental models in my head. However, through learning Rust I realised I had some gaps in my mental model of JavaScript so I wanted to share what I learnt thanks to being forced to compare what Rust does versus what JavaScript does.
I’ve worked with JavaScript for a while and I was vaguely familiar with its runtime but really didn’t know much about the details. I knew that you wrote some code and then in the right environment that code should execute and perform whatever piece of functionality was written in the code.
But when learning about Rust I realised Rust didn’t have an interpreter and JavaScript did. I stumbled across this when trying to use the .clone() method in Rust. I don’t want to get too deep into the Rust details but essentially I wanted to use this .clone() method and it didn’t work. I had to put some code #[derive(Clone)] into the file in a particular spot and it started working.
This piece of code implemented the Clone trait which essentially allowed me to use the .clone() method. But why do I have to do this step? In JavaScript, I wouldn’t have to do such a thing. Either this .clone() method would work or I would have to import it from some third-party package.
This led to me finding out that this is a compile-time feature. As Rust is a statically typed language vs JavaScript which is a dynamically typed language they work very differently.
As Rust is statically typed it relies on compile-tile checks to enforce its safety guarantees. Rust has a strong emphasis on memory safety. The way that the .clone() method requires the Clone trait in order to work is part of that system.
JavaScript on the other hand is dynamically-typed, which means that variables do not have types; values do. In a dynamically typed language, there are runtime introspection capabilities. This means that the program can modify the structure and behaviour of objects at runtime. Rust doesn’t do this. JavaScript is highly dynamic so it can manipulate types, functions, and more during the execution of the program.
To give a simple example:
JavaScript can check the type of a variable at runtime using the typeof operator or instanceof for objects. In Rust, you need to declare the types upfront before compiling (technically you don’t always need to declare because Rust’s compiler can often infer the type).
Rust’s design philosophy emphasises safety, performance, and concurrency, leading to certain trade-offs compared to languages like JavaScript. One of these trade-offs is the limited support for runtime introspection and modification of the structure and behaviour of objects.
However, just because Rust has limited runtime introspection doesn’t mean that runtime introspection is inherently bad. It’s just every programming language has its own set of goals and use cases and therefore the language is designed with those in mind. Rust aims to be super efficient and runtime introspection impacts performance. JavaScript is super dynamic and is used predominantly on the web so runtime introspection really helps.
Another thing that confused me when learning Rust was the “Standard Library”. I found myself importing methods from Rust’s “Standard Library” and realised I didn’t have to do such things in JavaScript.
Rust has clear documentation about its standard library. To use some functions from the standard library you type:
JavaScript doesn’t really have a standard library (it’s a bit confusing because some people claim it does and some claim it doesn’t — it definitely doesn’t have an import std like Rust though). JavaScript has many useful functions built into the language itself. If they aren’t built in then you are importing these functions from external packages usually found on npm. This can sometimes cause issues as these packages are maintained by random developers so there is a lack of oversight over them.
In JavaScript, there is garbage collection. It’s a way to manage memory. Essentially JavaScript handles the clean-up and reclamation of memory meaning you as a developer don’t have to worry about it. Imagine you are walking along and you are eating sweets and dropping the wrappers on the ground. JavaScript cleans all that up for you so when you look back it's all nice and clean. You don’t have to worry about cleaning up after yourself.
Rust however doesn’t have a garbage collector in the traditional sense. Instead, Rust has an ownership system that helps it achieve memory safety and automatic memory management. This ownership system is enforced at compile time so you can’t compile your program if there are potential memory leaks. It makes you really pay attention and attend to all parts of your program when developing to make sure nothing will potentially leak.
This does slow you down initially in development as there is much more to think about. It’s also one of the reasons why Rust is hard. There is much more you need to hold in your head at once and many more details to attend to. Rust is not going to let you get away with what JavaScript does. Coming from JavaScript this is a very painful adjustment.
I have realised through learning Rust that programming languages are built and designed for specific purposes. Therefore to say any one programming language is bad just doesn’t make sense. It really a case of choosing the right tool for the right job.
If you want safety and performance then Rust could be a better option. If you need something to implement some effects in a Web Browser then probably JavaScript will be a better fit.
I think it’s really important to try out different languages because they can help broaden your perspective. It also helps build up your toolkit so you have more options available to you when taking on a new project.
Loading...
Adam Drake is a Frontend React Developer who is very passionate about the quality of the web. He lives with his wife and three children in Prague in the Czech Republic.
Adam Drakes Site © 2024