Arguments against Scala language

I hope this post is not inappropriate but I would love to hear your arguments. I am not suggesting scala is bad, just asking so please don’t be mad at me. I am currently learning scala and planning to work in the functional paradigm and I was searching for a beautiful modern functional language that I can have a full-time job and scala seems really promising (FP and lots of jobs offer). But I found not everybody thinks scala is great language. Here is a Reddit post where you can read how verbose, badly designed, not acceptable as FP, language for naive FP newbie and disastrous scala is compared to f#.

Can I ask you if you can give some arguments against it and that scala is a good language for pure FP (with libs like Cats 2)? Or maybe scala 3 will improve on expressiveness or ambiguity? Or maybe you can point to some discussions that are already there on the scala forum. Have you tried f# and can compare how scala work in big projects and that f#? I personally can’t believe that so many intelligent programmers were using scala if it was that bad.

Here is one comment from there:

I just think Scala is so badly designed that it borders on unusable for programmers like myself. I’ll try to go into more detail, but beware, I’m in rant mode :slight_smile:

Scala’s attempt to ‘fuse’ FP and OOP is one of the many things that hurt its design. It was wrong-headed to try to fuse two entirely orthogonal language concepts , and the results were predictably disastrous.

The major practical point of moving to a functional language is to get away from OO thinking. Unfortunately, Scala’s fusion-ness makes that nearly impossible. You can’t do FP without OO because the syntax (and even semantics) for each is overloaded for the other! Having less keywords in a language can be nicer, but overriding their meaning (and worse, semantics) to achieve that is many times worse.

Objects are great when you actually need them (EG - for components) but object- orientation is just not good in most situations. Coupling program behavior with representation generally inflicts much incidental complexity in programs (http://fsharpforfunandprofit.com/posts/cycles-and-modularity-in-the-wild/). See also Scala’s atrocious collections library in detail.

Scala constantly violates the principle of least surprise nearly everywhere in its usage, whether you’re an OOP or an FP person. From which perspective was X language feature designed? One or the other, sure, but you’re typically left guessing, then referring to the spec.

There is almost no consistency in or predictable model of thinking for how Scala is defined. People still can’t pinpoint what the basic programming idioms for Scala should be! This partly goes back to the fusion, but also can be blamed on Scala’s general incoherence of design.

Scala is hugely complex with surprisingly little payoff in expressiveness. This is especially true for the type system. We get the complexity of type inference multiplied by that of implicits / sub-typing / variants / etc. The complexity of the type system is combinatorial! At the same time end up with weaker type inference than F#.

Scala’s design seems to have been generally incoherent - throwing together features that either failed to add to or actually detracted from its whole. Did we really need co/contravariants to make the type system even more incomprehensible than it already was? Maybe, due to its mutant fusion of OOP/FP… But that’s where coherency in design decisions must come in!

Scala essentially combines the complexity of C++ with the speed of Java. It combines poor-support for generic types with a very ambitious type system. It really is the worst of many worlds.

To avoid going on too long, Scala is just a failed experiment with a long enough feature list to attract naive programmers and functional newbies. While we should perhaps applaud the gumption it took to take such an experiment as far as Scala has been taken, now that the failure is clear in hindsight, we need to call it what it is.

1 Like

Whoever wrote the question above apparently doesn’t understand the purpose of covariants and contravariants.

The harshest criticism of Scala seems to come from people who try to use more advanced language features than they need to get the job done. They get confused and assume that the language is unnecessarily complicated when in fact they are just trying to use more advanced features than necessary for a particular problem.

The vast majority of programming problems can be solved in Scala as simply as or simpler than they can be solved in any other language. The complicated features are for more complicated problems, but bad programmers try to use complicated features when more basic features will do the job.

For my purposes as an aeronautical engineer, I have never needed or used covariants or contravariants, and I’ll bet most application developers don’t need them either. They are mainly for library developers.

As for OO, it may be overused, but it has its place. I rarely use OO inheritance, but I’ve dealt with problems where it makes sense. Again, the trick is to know where it makes sense, and that takes good judgment.

6 Likes

Many of the arguments in that quote are quite subjective. For me, the fusion of OOP and FP is one of the best things about Scala. Pure OOP or pure FP just don’t work for me - I need a mix of both. And while Scala’s type system maybe complex, it’s not overly so, and with the removal of existential types, it makes complete sense to me. Implicits are some of the most useful features in Scala 3: you can use them for everything from typeclasses to proofs.

But it depends from person to person. Some people, such as myself, love it, and some, like this person, think it’s a failure. You’ll just have to try Scala yourself to see how you like it. Scala may not be a particularly easy language to learn, but you don’t have to learn all of it at once. When I started learning Scala, I started with the basics and was amazed at its expressiveness, and after that, I slowly learned more advanced features, one by one. While it took me a couple months to grow familiar with it, it was just a hobby at the time, so if you pursue it more seriously, I’m sure you could learn it in less time.

Good luck, and I hope you find the language that suits you best!

3 Likes

Here is an interesting article on FP vs. OO:

https://blog.cleancoder.com/uncle-bob/2018/04/13/FPvsOO.html

3 Likes

So like with pretty much everything you can hear people saying that Scala is trash for X or Y reason where both X and Y are completely opposite.

Most of the time you would hear the opposite, that Scala is pretty difficult because of all the functional aspects; anyways let me try to share what I think about most of the points you shared.

Scala’s attempt to ‘fuse’ FP and OOP is one of the many things that hurt its design.

AFAIK F# is also a mix so not sure what his / her point is.
Actually, the little I know about F# was because I researched about it in my university for a class on programming paradigms and the cool thing of F# was being multi-paradigm (although I believe you have like to turn one paradigm and shutdown the other, not literally).

I actually liked the idea of being multi-paradigm but never liked the syntax, similar to how I liked my FP class but never like Haskell; thankfully I learned about Scala after that.
(BTW, and a bit in rant mode, I was looking at the code I wrote for that presentation and dude, I can’t read it the syntax is way complicated; I can read and understand older Java projects but not that)

The major practical point of moving to a functional language is to get away from OO thinking.

This just shows that the person writing this doesn’t really understand what OOP is, what FP is and what imperative programming is.
Yes, one usually embrace functional programming to avoid practices common in traditional imperative and object-oriented programming languages, but that doesn’t mean that OOP as a whole is bad and that you can’t or shouldn’t use that on a functional codebase.

But overriding their meaning (and worse, semantics) to achieve that is many times worse.

No example was shown. I can’t think of a keyword that has multiple and different meanings on its own; the only two things I can think of is the multiple meaning of _ which I do agree sometimes it is abused but in general, it means “anything” or “everything”, and implicit which depends on the rest of the line, and yes that was a pain point that is addressed in Scala 3.

Objects are great when you actually need them (EG - for components) but object- orientation is just not good in most situations. Coupling program behavior with representation generally inflicts much incidental complexity in programs.

So here he / she is contradicting himself / herself. Because nobody forces you to write Scala programs like this was Java with lambdas; even more, such style is discouraged.

See also Scala’s atrocious collections library in detail.

I have mixed feelings here.
I personally also believe that the collections library is way more complex than needed, I have discussed with many of their contributors how I personally feel most of the abstractions they provide are “useless” and how I personally would prefer if it was really a bunch of concrete types and a lot of typeclasses.
Yet, I immensely value all that the stdlib provides for us and the work and motivations of the authors and maintainers.

In the end, most of that complexity is transparent to users and it is actually pretty powerful so I would never call it “atrocious”.

Scala constantly violates the principle of least surprise nearly everywhere in its usage, whether you’re an OOP or an FP person. From which perspective was X language feature designed? One or the other, sure, but you’re typically left guessing, then referring to the spec.

Again an example would be good.
I actually have never felt surprised by a Scala feature in a bad way, I usually feel surprised for how cool / useful / interesting / powerful some of their features are.
The elephant in the room is initialization order which can cause damn hard errors, but at least we have tools to diagnose and fix that.

There is almost no consistency in or predictable model of thinking for how Scala is defined. People still can’t pinpoint what the basic programming idioms for Scala should be! This partly goes back to the fusion, but also can be blamed on Scala’s general incoherence of design.

While he / she has a point in that there are many ways to write Scala code, I always believe that is a feature, not a bug. It gives you the power of freedom.
Yes, as with everything, it has its bad things, newcomers have to choose and sometimes you may find a great library that is intended for the other style.

However, there is a minimum base with most of us agree with (yes there will always be extremists):

  • Using Option instead of null - specially for public things.
  • Being immutable in general, especially for public operations - that may be implemented in a more imperative / mutable form if that makes it more efficient or more readable.
  • Prefer higher-order functions like map, filter, exists, foldLeft, etc; instead of plain iterations.
  • Take advantage of the guarantees of a strong type system.
  • And many but not all like to turn errors into values instead of throwing exceptions.

Also, for newcomers they can start with just vanilla Scala and then pick up an ecosystem latter when they have more experience to make the decision.
And finally, there is usually possible to mix those ecosystems to some degree when that makes sense or when you want to migrate.

Scala is hugely complex with surprisingly little payoff in expressiveness.

Compared to what?
Like I tried googling and I do not find an equivalent of copy nor a way to define typeclasses in f#.

Also, yeah **Scala¨¨ is complex yet I have found it easier to learn and teach than Python the king of simple languages.

This is especially true for the type system. We get the complexity of type inference multiplied by that of implicits / sub-typing / variants / etc. The complexity of the type system is combinatorial! At the same time end up with weaker type inference than F#.

Yeah, yet I mostly never have type inference problems, many of them are easy to fix and most of them will be fixed entirely on Scala 3.
On the other hand, we have all the advantages of having such a powerful type system.

Did we really need co/contravariants to make the type system even more incomprehensible than it already was? Maybe, due to its mutant fusion of OOP/FP… But that’s where coherency in design decisions must come in!

Sure and Haskell keep saying subtyping is unnecessary and that a Monad is not an Applicative, and Python and JS people keep saying that types are unnecessary. - Oh wait, no, they either changed their minds, or keep denying even after more and more evidence says the opposite.

Scala essentially combines the complexity of C++ with the speed of Java. It combines poor-support for generic types with a very ambitious type system. It really is the worst of many worlds.

Do this person even knows what C++ is?
What is even wrong with the speed of Java on the long run? Have you even heard of GraalVM?
What does he / she means with poor support for generics?

To avoid going on too long, Scala is just a failed experiment with a long enough feature list to attract naive programmers and functional newbies. While we should perhaps applaud the gumption it took to take such an experiment as far as Scala has been taken, now that the failure is clear in hindsight, we need to call it what it is.

Sadly that the F# experiment failed in a way that now they are waiting for C# to overcome it.


Now, really, if you are going to criticize a language it would be good to provide points of your critics.
Scala does has bad things, like anything in the world, and many of us are working to make it better.

5 Likes

Agree, this kind of subjective one-sided ranting takes far less time to write than it does to counter or refute in detail, but that doesn’t make it true.

My own impression is that the author seems to have some bitterness, some personal cause for this axe-grinding, that they aren’t disclosing. But who can say?

6 Likes

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.