What are some of the advantages of using Scala over rust , C++ and other native languages?

IIRC future releases of Scala 2.x will be getting closer to what Dotty represents to ease the migration.

Claim that reification makes things easier is also unsubstantiated. If you really want to have a single method that works for two types of lists then you can use typeclasses, like here: spray | Blog » The Magnet Pattern

Is there something useful you can do in C++ using templates, but you can’t do in Scala using implicits?

Truly so. And, I am not about to substantiate that because I never claimed it in the first place. :slight_smile: I was only rejecting the alleged superiority of the Scala type system over the C++ one in presence of erasure in the former.

There is. But, I’d rather not open that in this thread (on the pluses of Scala over C++ and not vice versa). I might even not open it up on the Scala list either for I’m not sure this is the right place.

But, if you’re really interested, there are periods in my history on the old Scala mailing list when I pick that up when the occasion shows up itself. The Scala community doesn’t seem to be ready to learn from that and I have given it up.

Well, it would be nice to see a specific example of what you’re not able to do in Scala because of erasure. Hopefully on the simpler side. We know there are plenty of type-level tricks that are possible in C++ but in my Scala experience problems with erasure are usually a sign that a redesign would help.

Not many people care about performance, I don’t. Syntax sugar that enable you to write fluent code really matters. And JVM is fast enough for almost everything.

1 Like

It’s an old thread, but I was looking for ‘valhalla’ and checked if my question was answered here, but I found statements I heavily disagree with, so excuse my necromancy.

Erasure is a problem only with primitive types, only in Scala 3 (not to), as boxing is costly, especially in somewhat unpredictable GC (although the newer JVMs had made a HUGE progress in world freeze times).

  1. First, Haskell has the most advanced and robust and safe type system of all languages [citation needed] - casting is utterly impossible. Also, Haskel erases everything in runtime.
  2. I agree that you lose some information that would be handy if you wanted to heavily use reflection (although I don’t know if it possible in C++ at all, almost certainly not in Rust). However, Scala 2 has TypeTag, which lets you demand from the compiler everything it knows about the type. TypeTags basically let you access the whole AST of the type, resolve type aliases, type parameters - everything. Its problem is that you have to demand it in a place full type information is known to the compiler (obviously) and then pass through generic code (as an implicit parameter, so it is not a huge bother) to the place of use - you can’t just write a generic method asking for a TypeTag[A] and then call it from a generic method which doesn’t require it (it works exactly as exceptions in C++ if you insist on having a throws code in every method). Scala 3 lost TypeTags (maybe some weaker replacement will emerge as a library), but has an extremely robust and extremely simple macro system. The only language I know of that has easier macros is Lisp/Closure, and they are dynamically typed and ugh. I disagree with the official stance that you can do almost anything you could with TypeTags at compile time, but you indeed can a lot.
  3. As Java/JVM don’t support generics for primitive types (i.e., int, long, etc.), this results in boxing
    (a new object is created each time you use a primitive type through type parameteric code, which is much costlier). However, Scala 2 addressed this issue with specialization: you can demand that the compiler generates a separate class for listed primitive types, just as with C++. Unlike with C++, those types are subtypes of the erased (generic) type. It is a bit clunky in that you need to know how it works (a short web article will do it) in order to avoid really confusing errors. Unfortunately, it works only for built in primitive types, so if you can’t fit your information on 64 bits, no luck. Unfortunately, you can’t have a Set[MyType] without boxing. (You have some wiggle room if you can pack all your data on 64 bits).
  4. Unfortunately, Scala 3 doesn’t have specialization at all. I assume it is because Java 19 has just introduced full fledged support for value types (i.e. stack allocation, unless the object escapes closure, then it is transparently moved to heap memory). It still doesn’t have support support for using those value types with generics, but it is something they work on.
  5. Erasure also has its advantages, beside the obvious lesser footprint. You can write some tricky optimised code.
  6. Finally, I strongly feel that the claim that C++ has a more robust type system than Scala couldn’t be more wrong. The only language I know of that can rival Scala in expressiveness of the type system is Haskell. In what language for example, can you write this:
/** takes a Spellbook and returns a Spellbook guaranteeing 
  * that all spells have been loaded from the database. */
 def checkIfSpellsLoaded[S <: Spellbook](spellbook :S) :Option[S { type SpellsLoaded }] =
    if (spellbook.spellsLoaded) Some(spellbook.asInstanceOf[S { type SpellsLoaded }])
    else None
 def checkIfOwnerLoaded[S <: Spellbook](spellbook :S) :Option[S { type OwnerLoaded }] =
     if (spellbook.ownerLoaded) Some(spellbook.asInstanceOf[S { type OwnerLoaded }])
     else None

You can compose those functions and obtain flag for all loaded relationships. No copying. You can create a type alias to reduce the noise, for example type SpellbookWithSpells = Spellbook { type SpellsLoaded }, but the huge advantage of the other is that you can have any number of such type flags.
Think now that you have three such flags in your Spellbook - you would need 8 specialized subclasses to create, and then everywhere where you create an instance of Spellbook you would need to handle those 8 cases. Unfeasible. Scala type system is plenty strong, and actually benefits with caucious casting hidden in libraries, for example - in general, avoiding it completely can sometimes greatly complicate otherwise quite simple code.

In general, in Scala, you have to think compile time rather than runtime, which is the reason we use statically typed languages in the first place. My personal belief is that the compiler should find all bugs with the exception of the trivial ones - i.e., those, whose both reason and fix is obvious the moment you discover it. I think that Scala’s type system is close to being strong enough to do it, and it’s more typing than you probably wish to handle anyway.