I’ve used Scala for a long time, used C++ for years and years before that, and dabbled in Rust for as long as it was there to dabble in. So all this is my opinion, but it’s at least opinion honed after a good deal of experience.
The advantages of using Scala over both C++ and Rust are:
- You can use the JVM. There’s a huge ecosystem of libraries and a huge amount of knowledge in how to deploy things on the JVM, keep them running robustly, and so on. It is much easier to achieve these things on the JVM (for now) than in any other context.
- You have really powerful abstraction mechanisms, an amazing collections library, and a very DSL-friendly language, allowing you to write code at a higher level and offload (safely!) many problems to the compiler once you figure out how to express them.
C++ and Rust will, if used moderately carefully, run considerably faster than Scala for performance-critical tasks, most especially when using generic code that handles primitive values (integers, etc.). Generally in carefully-crafted areas you can often get 2-3x faster in C++ or Rust than Scala or Java. A lot of it comes down to you caring enough about performance to design for performance ahead of time, and the profile and microbenchmark afterwards. You have to put in a pretty serious effort before the language choice matters more than your will to make things fast in the language you’ve got.
The earlier comment about garbage collection being an advantage is wrong. If you don’t know how to use C++ and Rust properly, maybe you’ll end up in a situation where a GC actually helps you. You really have no excuse whatsoever with C++ to lose to a GC system, though, if you care. With Rust you have a small excuse–memory arenas require placement new which you get in nightly only for now. But really, the extra work that the GC has to do in checking, pointlessly, to make sure you still haven’t lost your reference to something is quite considerable. If you’re going to use C++ or Rust and not think at all about how you create or use memory–well, true, it’s not going to be super-fast, and it won’t be all that fast in Scala either, so are you sure you really meant to go fast? Anyway, Rust excels at efficient multithreaded programming; if you insist on “functional” instead of “correct and safe”, you’re doing it wrong. Rust will help you get it correct and safe. C++ won’t, but should you happen to get it right anyway, it, like Rust, will outperform Scala or anything else on the JVM.
Rust is very good for writing code that will not go wrong, even though you are forced to think about ownership of variables all the time. The compiler will check you. I feel much more comfortable that my Rust programs are free of problems that could be detected at compile-time than I do with Scala. With C++ and lots of templates, it’s kind of scary. (Python, for comparison, is a terrifying free-for-all.)
Although Rust is not quite as good at Scala at allowing you to write high-level code, it is pretty good at writing safe time-saving abstractions. I choose it over C++ whenever I can (which isn’t very often, since I have a lot of C++ code and use things like SIMD a lot which aren’t stabilized in Rust yet).
If you want to program in a pure functional style, Scala is also the best, due to the advanced type system. Rust’s type system isn’t yet quite up to the task of talking about complex type constructs (technically, it doesn’t have higher kinded types yet and there isn’t even a plan for traditional HKTs; it will be getting associated type constructors which can handle some of the complexity). Note that Rust’s safety guarantees pretty much eliminate the need to use immutability for safety; you can still get yourself into trouble by mutating things without realizing it, but you can also use functions to return new values and then forget you’ve done a type-preserving transformation. Do not use C++ to program in a functional style; closures have awful syntax, and the interaction with templates is weird, and the error messages you get when something goes wrong are exceedingly long.
If you want it to be really easy to pick up and use external packages, Rust and Scala are so far ahead of C++ that the difference between them hardly matters. Rust’s cargo build tool excels at making things simple. Scala’s build tools are all more complicated, but JVM deployments are often more complicated, and the tools will help you with that.
If you like object-oriented programming, Rust doesn’t really have that; it uses a trait system instead that has some but not all of the code reuse and abstraction capabilities of object-oriented programming. C++ and Scala both have first-class OOP capabilities. Neither really is a clear winner there; they both have their wrinkles. Scala’s is geared more towards compile-time safety with generic code working properly at runtime, while C++ is geared more towards code generation via templates. C++ usually performs better as a consequence, but Scala has more comprehensible error messages (and more comprehensible complex types, at least to my eye).
If you need to access hardware, stay away from Scala and the JVM. The whole point is to abstract that stuff away. The JVM makes FFI relatively awkward, so you can’t use it to add functionality to other platforms either. If you want to write a module for something else (Python, let’s say), it’s got to be C++ or Rust. You could try Scala-Native, but it’s still early in development.
If you don’t like having to think about memory, use Scala! Rust makes you think about it all the time, and helps you think about it. With C++, you can think about it or not, and it will help you a bit if ask it to, and crash at runtime if you didn’t think about it when you needed to. Overall, for “don’t worry about memory”, Scala is clearly in the lead.
If you want to target Javascript, use Scala or Rust. Rust has a webassembly backend, so it can make JS-compatible stuff that’s blazing fast. Scala.js seems like an easier integration to me for pure Javascript, though. I haven’t used either extensively. C++ isn’t good for this.
Scala has a REPL. Trying to do this in C++ or Rust is awkward at best. If you like programming and testing things live, this is a huge benefit.
Anyway, to reiterate: Scala can take advantage of a HUGE ecosystem of libraries for the JVM and gives you the build tools to consume them easily (C++ has a HUGE ecosystem that is hard to use, and Rust’s ecosystem is still quite small and using non-Rust libraries gives a poor experience); has a highly advanced type system that includes both functional and object-oriented capabilities giving you a larger and more potent set of tools for effective abstraction and code reuse than in either C++ or Rust; and has a powerful straightforward set of collections that help you turn a ton of really common tasks from half-page functions into one- or two-liners (more effectively than C++ or Rust can).