Rust — from the point of view of a Scala developer
I’ve decided recently to give it a shot and try to do some programming in Rust. I remember those days when I used to code in C/C++ (and even on devices with 48Kb RAM), so it was a bit indeed nostalgic for me as well. Nowadays, I’m using mostly Scala, Java, Haskell.
This would be my personal experience, so all opinions are my own and subjective.
Tools
I’ve started my journey with IntelliJ IDEA Rust plugin and that was the first my mistake. Surprisingly, afterwards, I found out that there are two different versions of Rust plugin from IntelliJ. The version for IntelliJ CLion works differently and has debugger support, for example.
I learnt cargo tool and its ‘toml’ file format really quickly (sbt or cabal/stack is much more complicated to compare with).
Overall, the tools for Rust mostly are good and mature enough. I have only one big issue with Rust plugin for CLion — it doesn’t work properly with the generated artefacts from procedure macros (the details here). It is really annoying, working without properly working autocomplete in this scenario.
Language
I have had no issues with Rust ownership/borrowing approach (it wasn’t a real issue for me after years using C++ and dumb/smart pointers), but I can understand some frustration about it from other developers.
Traits/impl are really close to instances and type classes in Haskell, so I feel appreciated that they also exist in Rust.
Annoying things:
- structs without default values — after case classes from Scala, you need a lot of macros to support and boilerplate to do something similar (yet still not good enough).
derive(Default)
andDefault
trait aren’t the proper answer for me (as well as in Haskell — the records in Haskell are still killing me). - absence of named arguments in functions — you can live without it, but I will definitely miss this (especially because you also don’t have default function argument values).
- absence of higher-order functions and higher kind types
- absence of FP primitives/common functions (even something common like
Option.flatMap
, for example). - huge usage and dependency on macros system — they are literally everywhere, and your code is full of
#[attributes]
(they resembled me sometimes the code written in Java/Spring with a zillion of annotations). I’m not sure if it is a good sign.
Goodies:
- Safety without compromising efficiency. And this is really impressive how to solved in Rust — unique ownership concept embedded in the language itself.
- No JVM, no wasting your RAM excessively (and living in the world without
Class.forName()
surprises, GraalVM workarounds). It is crucial for “serverless” and “microservices”. - Having parametric polymorphism (hello there, Go lang), Haskell like type-classes, solid support of pattern matching and immutability first principle.
- WASM is available for you today (it is still not available for Scala.js/native yet, for example).
- Many language keywords are short (
fn
,pub
,mod,
types) and thanks gods for that. I still rememberfunction
from JavaScript. They are short yet still readable. - Cargo tool is easy to use and learn. I published my first cargo with my own macro implementation without any issues on the same day as I started to use it. Not saying it is perfect, but I had been afraid of learning yet another build tool.
- Compiler error messages — it seems they did a really good job on this one.
Overall, I think Rust has a great and solid start. I will not migrate completely from Scala to Rust (especially when Scala 3 come, Scala is still much powerful language than many others), but it is definitely a great addition to the tools you can use to implement some cases (serverless, some microservices, low-level programming as a C replacement, WASM, …).