Arguments against Scala language

Aside from the points already countered by others, note that the reddit post is 6 years old. Most likely, the poster had experience with Scala 2.10 or even earlier.

A lot of the points in their comments in that thread are in areas, that have changed a lot since then. For example, the collection library was completely reworked in 2.13, removing a lot of the uglier parts (e.g. that whole CanBuildFrom business). Type inference and exhaustiveness checking, which they criticize, has also improved.

4 Likes

Some further discussion on more or less the same subject happened starting at https://contributors.scala-lang.org/t/scala-3-versy-impressive-it-can-replace-python-i-think/4768/11?u=sethtisue

1 Like

you mean redirect to “scala 3 very impressive” or this question should not be on scala users?

I already tried but it didn’t work. oh well

2 Likes

I have locked a third thread, Productivity, design and conciseness of Scala , and redirected it here

1 Like

And another one: Tradeoffs Scala had to make in order to support both FP and OOP

@karolwolonciej please slow down and think twice before starting any more topics in this vein, unless you truly have something new and separate to ask

2 Likes

Yeah, there are a lot of haters, which doesn’t really matter, what matters is actual arguments, except that increasing Scala’s popularity is a problem we have to solve.

Note that it’s 6 years old. F# is indeed less verbose than Scala, as well as than most languages, and in some ways is more functional. But that’s true of F# vs. most languages. In general most of the criticisms of Scala are unsubstantiated and either wrong or apply to most popular languages.

Scala is a great language. In general I don’t know if there’s any single respect in which Scala is the best but in the big picture it’s the best because of the way it’s great in so many different ways, unlike many languages which are either excellent in one respect and mediocre in other respects, or are just mediocre in general.

If pure FP is your only consideration then Scala might not be your best choice, but if it’s a major goal along with other goals then you have to compare how other languages score against your combined goals.

Cats is an amazing library. You can call it FP or not, it doesn’t matter, you can think of it as a utility library that covers so many things so efficiently. Cats-effect is about pure, monadic FP effects, which is great on top of cats. And Scala 3 is even greater in many ways.

Scala is one of the most carefully and expertly designed languages. If there’s any valid criticism in this regard it’s that a beautiful design might be in conflict with perceived simplicity, which raises the question whether the goal of language design should be perceived simplicity or power. I like Scala for its power, and if some essential complexity is the price for that I’m happy and maybe that’s not to everyone’s tastes but it’s there for whoever needs it.

That synergy is precisely Scala’s raison d’etre, its thesis That its defining characteristic. If you want pure OO or pure FP then it’s not for you, the same way that you can’t complain that Haskell isn’t OO or that knives are sharp.

And it’s a thesis that almost every popular language has coveted. C# has become more functional, and Javascript more object-oriented, since this was written. And Kotlin went running with it.

It doesn’t sound like he knows what orthogonal means. It is precisely their orthogonality that makes them so fusible.

Again, very imprecise language. I think he means that FP and OO are in conflict (they are not) and that many scala features have an FP/OO duality. For instance functions are just objects with an apply method, and constructors are done by putting parameters on the class itself. That’s synergy, not overloading/overriding.

No, all features were designed for both. This criticism sounds like it would be better directed at F# from what I’ve heard.

That is very not true. It’s just very different than most languages. Unfortunately Scala is not taught that way enough, so people don’t appreciate it. It’s like describing a fork as “a spoon except with no ability to hold liquid and pointy things coming out of it.” From that perspective it’s bad design indeed, and worse than useless.

Again, this is looking at a fork with the spoon mindset. Scala is a wide tent. It gives you freedom. It doesn’t hold your hand or have training wheels. It’s a very deep and flexible language. So there isn’t a single set of idioms. You can use any idioms.

That said, over time we have gotten a much better sense of what idioms don’t work well and what idioms do. Sometimes that’s based on limitations of Scala, but sometimes it’s because you can’t experience certain choices without freedom, and so in fact these learnings can apply to any language, existing or hypothetical.

This couldn’t be further from the truth.

How is type inference complexity?

In general the complexity of orthogonal things is combinatorial, but because they are orthogonal it isn’t harder.

Also, based on this I guess this guy would never have predicted the success of Typescript, which has much more complicated types than Scala.

The weaker type inference is mostly a necessary result of the more powerful types.

I guess this is an argument against C# too?

I guess he wouldn’t have predicted the success of Rust either

The JVM is actually the best choice if you need speed over time, and don’t have a lot of time or expertise to hand-optimize things or the patience for writing Rust.

7 Likes

@karolwolonciej trying to address your point in “Tradeoffs Scala had to make in order to support both FP and OOP”.

This is something people more familiar with the language specs and / or the compiler could answer more objectively.
But, I would guess the simple answer is the complexity of the language.

Now, that a language is more complex as a language is not bad or good on its own, is what you do with that complexity., where is contained, when it is leaked and what you win for that.

IMHO, Scala, in general, does a great job on containing the complexity inside the barriers of the language and std library (and in an extent to third-party libraries) such that it doesn’t affect users and thus only providing them with the power.

There are exceptions, of course, like implicits (being reworked for Scala 3), view bounds (deprecated IIRC) or implicit conversions in general (discouraged by the community and made safer on Scala 3 for when they make sense), variance which always pops-up on beginner tutorials (like writing your own List) and scares people but the reality is that most of the time you do not need to care about it and only enjoy its advantages like the collections library (and actually understand it is not that hard IMHO).

Now I would say that most complexities of Scala came from running in the JVM and supporting interoperability with Java.

Things like null, the existence of abstract classes (and that traits didn’t have parameters), the differences between Functions & Methods, limitations on overloading, etc. Are probably consequences of that.
But then again, most of these are being worked on, and the advantages of such a decision simply outweigh the costs.

4 Likes

Can someone say if Scala 3 will do sth with this:?

We present short programs that demonstrate the unsoundness of Java and Scala’s current type systems. In particular, these programs provide parametrically polymorphic functions that can turn any type into any type without (down)casting. Fortunately, parametric polymorphism was not integrated into the Java Virtual Machine (JVM), so these examples do not demonstrate any unsoundness of the JVM. Nonetheless, we discuss broader implications of these findings on the field of programming languages.

From the title, it appears to deal with null pointers. The usage of null is discouraged in Scala, even in Java, in fact. Scala 3 seeks to fix some unsoundness in the type system, although I don’t know if the stuff in that article is addressed.

I tried it, and Scala 3 gives the same exception on the same program.

But I agree with ysthakur that this is even less of a concern in Scala than it is in Java. The paper’s audience is programming language theoreticians; it’s not intended as ammunition for language wars in industry.

Perspective: the bulk of our industry is on languages which no have no compile-time safety at all (Python, JavaScript), or not much ( C).

4 Likes

Can someone post that program (if it isn’t too long)? I’d be curious to see it. Thanks.

It’s figure 5 in the paper.

object unsound {
  trait LowerBound[T] {
    type M >: T
  }
  trait UpperBound[U] {
    type M <: U
  }
  def coerce[T, U](t: T): U = {
    def upcast(lb: LowerBound[T], t: T): lb.M = t
    val bounded: LowerBound[T] with UpperBound[U] = null
    upcast(bounded, t)
  }
  def main(args: Array[String]): Unit = {
    val zero: String = coerce[Integer, String](0)
  }
}
1 Like

Thanks. So is this worth fixing, or is it just some theoretical curiosity? And could it be fixed without a major redesign? Just wondering.

It’s not merely academic, because people may write real world code that runs into this issue. That doesn’t necessarily mean it is a big deal. I don’t know how hard it would be to fix this, but my guess is it would be very hard.

Wasn’t the primary motivation for rebuilding the compiler backend from scratch that Scala 2 was somehow unsound, but Dotty is sound, because it is based on DOT calculus?

I suppose there are two possibilities now: either Martin is going to invent the DASH calculus, which is really sound, and then create an experimental DASHy compiler which will morph into Scala 4, complete with Reverse Polish Notation. Or, he will prove the Odersky Incompleteness Theorems, which state that any sufficiently powerful type system is unsound, and then go on to invent new dynamically typed languages.

Am I safe if I dont use nulls?

DOT doesn’t have nulls.

So, Dotty/Scala 3 is not based on DOT, but DOT+Null, and DOT+Null is not sound?

In that case, there is a demand for a new sound DASH that replaces DOT+Null, or else proof that such a thing does not exist. Unless, of course, it has already been proven that it is impossible.

Avoiding nulls is a very hard problem. Nulls arise from interop and from initialization issues.

Interop nulls can be handled by containing methods calls that can return null and immediately handling the null.

Initialization is trickier. For example, you get null if you have initialization cycles such as:

object A { val x: String = B.y }
object B { val y: String = A.x }

Keep in mind that every type or object is compiled separately, and that the cycle may be longer than two steps, and may be obscured by inheritance, composition, type classes or chains of method calls.

Ironically, when someone asks for help with initialization issues, they usually get the advice “use lazy vals”, which solves many initialization issues, but not cycles.

Scala 3 should contain experimental support for null tracking.