> If you want to keep on writing Java, keep writing Java.
Ah! But that’s the point, because Scala is pulling a bait-and-switch. If it were only a modern statically typed language I wouldn’t complain so much about it (and I really do complain a lot about Scala, I guess). Yes, I find its gaudy indiscrimination aesthetically unpleasing[1], but that’s a matter of personal taste. The problem is that Scala still markets itself as “a better Java”, and people are drawn to it so they wouldn't have to write getters and constructors. And at first, Scala does seem to be that. Only after a while you realize that it’s a whole other beast altogether — not necessarily the one you bought into. If Scala were marketed as “a JVM language Haskellers can learn to live with”, I’d have no issue with it (except the aesthetics, that is :)).
[1]: Yet, with its near-infinite list of features it can't even type immutability, which even Java 8 can through its pluggable type systems.
Indeed, if Scala wasn't closely compatible with Java (in terms of both syntax and interop) it would not have so much traction. That's the deal with the devil that Scala made, and one reason it has an excess of cruft. For example, no language needs both traits and abstract classes, unless that language wants to interoperate easily with Java.
I am broadly agreed with you. Scala could do with trimming, and I'm optimistic that both Typelevel and Typesafe will accomplish this in the near future.
> For example, no language needs both traits and abstract classes
So abstract classes are the unnecessary bits in Scala? :)
Choosing to do it all at once shouldn't surprise you as it's kind of Scala's modus operandi. I would say no single language needs algebraic types and inheritance and structural types and dynamics (and implicits and macros).
The deal with the devil Scala made, IMO, is when it tried to be both a research language and an industry language at the same time (Java interoperability is but a small part of this deal) without realizing that what's good for research (many different ways of doing things) is often bad for industry.
It's the Las Vegas of languages: gaudy and confusing, but if you look at just a tiny part of it and squint, for a second you can convince yourself you're in Paris.
If you buy into object-functional, combining ADTs and inheritance as Scala does is quite reasonable.
It will be interesting to see what Scala is like in a couple of years. I think (hope) many of the issues will be resolved. Just going over the list you give:
- Implicits are useful. Implicit conversions, the evil part of implicits, are mostly going away via deprecation and other mechanisms.
- Structural types might go away if higher kinds are curried, or there is syntax for partially applying a higher kind.
- Dynamics. Who uses this? Why was it even added? I'd nuke it in a second but I don't know of any plans to remove it.
- Macros aren't even officially in the language yet, so it's a bit early to call for their removal :)
Ultimately is comes down to implementations. The idea of statically typed FP inspired languages has been around forever, but the implementations just haven't been up to scratch. Where are the alternatives to Scala (that is, statically typed, run on the JVM)? Things like Kotlin etc. are still in development and don't really offer much over Java. It might be in 5 years that Rust has a sufficient ecosystem to make it a viable alternative to the JVM. I think a lot of big data systems (in the area of Cassandra / Kafka / Hadoop) projects would happily move over to Rust, just to avoid GC issues. Haskell is the other alternative with traction, but it's an even further leap for most developers so I'm not convinced.
I prefer a much more pragmatic approach. From where I stand, statically-typed FP languages like Haskell are very interesting but are still in the research stage. We don't even know that that's a direction worth adopting in mainstream languages. Some ideas (pattern matching) are easy to understand, but others? Personally, I think static types going beyond those offered by Java could be very beneficial, but I'm not convinced that the type systems used by Haskell or Scala are the way to go.
We do know that FP does allow for more general abstractions, but those usually come at a cost. They are harder for people to understand, and frankly, haven't been proven to increase code quality and maintainability. Yes, they're elegant like mathematical equations, but equations don't need to be changed and maintained by large teams of people over many years. A language like Haskell gives you more tools to think of your program ahead of time at the expense of thinking about it when it runs (with a debugger, profiler etc.), and I'm not sure that's the tradeoff the industry should make. Math is a great tool, but I'd learn how to catch a ball a lot faster by trial and error, then by learning how to rigorously compute its trajectory.
I think people in the industry should wait for more evidence of the utility of the more advanced FP concepts before rushing to adopt them. Of course, that doesn't mean people should be working on novel approaches and trying them. But my problem with Scala is that it is really a research language that tries different unproven approaches (and that answers pretty much all your questions about why certain features were ever included -- that and the non discriminating taste of its designers). But it's dangerous because it tricks people into thinking it's something else.
The worst thing about Scala seems to be that the community always have to deal with a single nutjob on Jihad, first Harrop, then Colebourne, then Beust, now that guy.
I believe Clojure is less directly interoperable. For instance, a Scala class is a Java class. I believe creating a Java class in Clojure is something you have to call into a library to do.
Update: reading the Clojure docs, the main issue I see is compiling Java code against Clojure code. Clojure has a number of constructs for calling Java code and creating Java objects, but it's not clear to me how you define an API in Clojure that Java code can then call.
Actually, Clojure interoperates with Java much more cleanly, and easily than Scala. Every Clojure collection is a Java collection and vice versa. Every Clojure map is a Java map and vice-versa. Plus, because Clojure is less statically typed than Java, Java typing idioms don't clash with Clojure's.
> Plus, because Clojure is less statically typed than Java, Java typing idioms don't clash with Clojure's
Well, you made me laugh. :)
But the real deal is compiling stuff to JVM bytecode ahead of time, which Java code can then be compiled against. It's not clear to me that Clojure provides this, which is what I was getting at.
Ah! But that’s the point, because Scala is pulling a bait-and-switch. If it were only a modern statically typed language I wouldn’t complain so much about it (and I really do complain a lot about Scala, I guess). Yes, I find its gaudy indiscrimination aesthetically unpleasing[1], but that’s a matter of personal taste. The problem is that Scala still markets itself as “a better Java”, and people are drawn to it so they wouldn't have to write getters and constructors. And at first, Scala does seem to be that. Only after a while you realize that it’s a whole other beast altogether — not necessarily the one you bought into. If Scala were marketed as “a JVM language Haskellers can learn to live with”, I’d have no issue with it (except the aesthetics, that is :)).
[1]: Yet, with its near-infinite list of features it can't even type immutability, which even Java 8 can through its pluggable type systems.