Hacker News new | ask | show | jobs
by reality_czech 2783 days ago
Java has been gradually eating all the good parts of Scala. So far, it's eaten lambdas, map / reduce / fold functions, option types, raw string literals, the concept of a built-in REPL, type inference for local variables, and default methods in interfaces (which is kind of like mixins). Pattern matching and type classes are on the menu, but not yet formally merged into Java.

So what does Scala have left? Operator overloading, which tends to lead to unclear code. "Implicit," which should give any former C++ programmer PTSD flashbacks. A compiler which is pretty slow. The ability to embed XML into code (why?). A collections library which is nightmarishly complex. (See https://yz.mit.edu/wp/true-scala-complexity/ )

4 comments

> Java has been gradually eating all the good parts of Scala.

Horray! I remember the first time I poked at Java, back in 2007, and I hated it, in large part because it was missing these. It's fantastic it's eaten these good things.

> So what does Scala have left?

Style/syntax and community?

I don't know enough about either language to debate on the points you've brought up; what I do know is that Scala feels a lot more like writing Ruby/JS/Python than writing C++/C#/Java.

I've only just started writing real class definitions in Scala, and the way that "constructors" work really drives home this similarity and difference; the kind of code you write to define the class looks to be the exact same kind of code you write to define everything else.

I also haven't poked into the larger Scala community, but I can't imagine it's all that similar to the larger Java community. Even if Java reaches some kind of feature parity with Scala, I bet this difference remains, and it'll come across in the libraries, common usage patterns, help on the internet, and conventions.

Again comparing to Ruby, the effect that "Matz is nice" and (when you add in Rails) "convention over configuration" have goes beyond code features into what it's actually like to use and work with the language day in and day out.

> Java has been gradually eating all the good parts of Scala. So far, it's eaten lambdas, map / reduce / fold functions, option types, raw string literals, the concept of a built-in REPL, type inference for local variables, and default methods in interfaces (which is kind of like mixins).

If you adopted Scala 5 years ago, you could have had all the good stuff Java has today, 5 years ago. If you adopt Scala today you can have all the good stuff Java will be getting in the next 5 years, today.

> Pattern matching and type classes are on the menu, but not yet formally merged into Java.

How many years or decades will those "formalities" take? Java language enhancements have a history of taking much longer than originally claimed.

> Operator overloading, which tends to lead to unclear code.

The problem with traditional operator overloading is that you have to memorize which symbol corresponds to which magic method name (I can never remember what method * calls in Python, for example). Scala avoids that because it doesn't actually have operator overloading; rather, operators are just normal methods that you call in the normal way.

> The ability to embed XML into code (why?).

Already moved into an optional library, being dropped entirely in the next version.

> A collections library which is nightmarishly complex. (See https://yz.mit.edu/wp/true-scala-complexity/ )

Replaced in the next version. (And the complex parts were only ever for doing things that are completely impossible in any other language).

> So what does Scala have left?

Higher-kinded types (which let you represent secondary effects in a uniform way - obvious things like validation or async, but also custom effects like database transactions or an audit trail). Uniform representation of structures/records (via Shapeless) that lets you traverse data structures in a normal, type-safe way.

Put that together and you get a language where you never need the magical frameworks that (real-world) Java needs. No reflection-based runtime serialization that you have to control via a type registry separate from the language type system. No reflection-based database mapping that you have to control via another, subtly different type registry. No AOP decorators where you rename a method and it magically stops having a database transaction applied. No magical annotations for your http routes that tell it which string class name to load at runtime for serialization, where if you want your web threads to do something before/after you use yet another magic method or registry. No magical autowiring framework instantiating all your classes for you.

Just plain old functions and values. Standard language features (plus one macro in shapeless that might as well be part of the language for it's used) for all of the above. One standard syntax (for/yield) for effect management that all the language tools understand. Libraries for things that would be language features in most other languages, but without having to resort to the free-for-all of custom macros.

That's what Scala has. If Java catches up to that one day, great! But without higher-kinded types, and without some kind of uniform representation of records/case classes/data classes/what-have-you, it will never get close.

> The problem with traditional operator overloading is that you have to > memorize which symbol corresponds to which magic method name.

That's not even in the top 5 problems with operator overloading.

> How many years or decades will those "formalities" take? Java language > enhancements have a history of taking much longer than originally claimed.

Almost certainly a shorter amount of time than it would take to migrate our codebase away from Java. Oracle has actually been moving pretty fast with Java recently, for better or worse.

> [XML is...] Already moved into an optional library, being dropped entirely in > the next version.

And this illustrates another problem: Scala is constantly breaking backwards compatibility. Which is a real-world problem, unlike "I want the latest gee-whiz language feature."

> Put that together and you get a language where you never need the magical > frameworks that (real-world) Java needs.

Scala has plenty of "magical frameworks": scalaz, akka, shapeless, the list goes on.

Newer Java libraries like Jackson don't need a type registry (or at least, not one that have to manually set up.)

I won't try to defend J2EE or Hibernate, but also, I don't use them.

> That's not even in the top 5 problems with operator overloading.

What other problem is there? Some libraries define functions with stupid names and that's a problem, but it's a problem you have without operator overloading too.

> Almost certainly a shorter amount of time than it would take to migrate our codebase away from Java.

I rather doubt that; a typical codebase has a half-life of what, 5 years? Which is less time than many of the Java features you listed have been delayed for.

> And this illustrates another problem: Scala is constantly breaking backwards compatibility.

Hardly. One major compatibility break in the language's entire history, eight years ago; removal of XML literals will be part of the second, and is only happening after they've been a) universally agreed to be a bad idea and b) deprecated for four years and counting. Yes it's not quite the extreme levels of backwards compatibility that Java offers, but it compares favourably with most languages out there.

> Scala has plenty of "magical frameworks": scalaz, akka, shapeless, the list goes on.

Maybe some parts of akka (I don't use it), but certainly not scalaz or shapeless: they're libraries, not frameworks, and there's no magic (no reflection, annotations or anything like that, aside from the one macro I mentioned), just ordinary values and ordinary functions that you call in the ordinary way (even the macro behaves like one).

> Newer Java libraries like Jackson don't need a type registry (or at least, not one that have to manually set up.)

Jackson is the example I was thinking of actually, it absolutely does have a (magic, reflection-based) registry that controls how things get serialised. See e.g. https://github.com/FasterXML/jackson-datatype-joda#registeri... .

> So what does Scala have left?

This is why I think long term Groovy is better positioned than Scala, even if short term Scala has more of the mindshare. Groovy actually offers something fundamentally different, while Scala is perpetually trying to compete on Java's home turf. If people really want a pure, statically typed language Kotlin is pretty good and has less impedance mismatch with Java.

> If people really want a pure, statically typed language Kotlin is pretty good and has less impedance mismatch with Java.

I see this the other way around: Java genuinely has eaten most of the good parts of Kotlin, because Kotlin is positioned as a small enhancement over Java rather than a language that brings major improvements as Scala does. Adopting Kotlin means paying much the same cost as adopting Scala, but for much less in the way of benefits.

This is why Kotlin is such a hit for Android devs, who are stuck with only half the features of Java 8 (at best).
What fundamentally different does Groovy offer?

What do you mean by "Scala is trying to compete on Java's home turf"?

When Apache Groovy was first released, it offered closures and dynamic typing on the JVM ecosystem, but nowadays Java has lambdas and inferred typing, so Groovy doesn't really have much fundamentally different to offer anymore. And since version 2.x, Groovy is also "trying to compete on Java's home turf" because it has static-typing annotations, but Kotlin and Scala are probably better choices if you want static typing on the JVM because it was baked into them from the get-go instead of being bolted on as in Groovy 2.x.
Groovy is a truly dynamic language (with all the pros and cons that come with that). So you can put it into contexts such as interactive scripting where Java will always be suboptimal and solve problems Java doesn't even want to solve. On the other hand, every single good idea that Scala comes up with will eventually be co-opted by Java, because there is no reason for that not to happen. It is just a matter of time.
When higher kinded types come to Java, please ring me up!
Touche - yes, I agree that Java is probably never going to attempt to introduce that!
Implicits are a sharp sword. Either very good or very bad depending on the people using them.

Scala doesn't stand still either. Dotty / Scala 3 will bring many refinements and new features like union types, opaque types and implicit function types.