I'm not from PagerDuty, but I also moved to Elixir after some years working in a hybrid Ruby + Scala shop. I concur with the author's experience that writing clean and maintainable Scala code is hard. A few reasons:
* Haskell influence on the language, especially early on, encouraged the omission of dots and parentheses wherever possible. Just about every piece of sample code was written as an undifferentiated stream of tokens. There is a mental burden.
* Haskell influence on the community encourages category theory solutions to all problems. This harms interop with Java libraries, in addition to requiring a number of concepts that are safely ignored in many/most other languages.
* Scala's rich OO system (classes, interfaces, traits, singletons, case classes, implicits, etc) results in frequent design paralysis, not to mention taking a while to learn.
Elixir suffers from none of these problems, while retaining some of the things that made Scala a pleasure to use, notably the actor system of concurrency and the use of immutable data structures.
I work for the Scala Center and I'd like to comment on some of the points you make to hopefully explain how I see things from my side. You can expect my opinion to be biased but I'll try to stick to the facts.
> Haskell influence on the language, especially early on, encouraged the omission of dots and parentheses wherever possible.
This is considered an anti-pattern in the Scala community. The last library that used this at large scala was sbt, Scala's build tool, and now everyone discourages the use of infix operators.
> Haskell influence on the community encourages category theory solutions to all problems.
This is simply not true. First, there is no Haskell influence on the language. Scala is a functional programming language, all similarities between the two are just fundamental to how their type systems work and the foundations of the paradigm. Second, I contest heavily that the Community encourages category theory to solve all the problems. There are many subcommunities in Scala and many styles, but if you talked to some Scala developers nobody would agree that category theory should be applied to all code. In fact, most people don't. They just use Scala because it's a better Java that boosts their productivity.
> Scala's rich OO system (classes, interfaces, traits, singletons, case classes, implicits, etc) results in frequent design paralysis, not to mention taking a while to learn.
Absolutely agree that for someone not experienced, it may be difficult to know what's the best way to design libraries (this is more of a problem with libraries than applications). This is a big problem of Scala that I think we're solving by making the language more opinionated and being more open about what's encouraged and discouraged.
If you ask for my opinion, I think we also need to make a better job at communicating all this knowledge that advanced Scala developers learn but that is usually kept to closed circles.
>They just use Scala because it's a better Java that boosts their productivity.
I spent three years on the 2nd largest Scala 'team' in the U.S (first as an engineer, then leading a sub team), the problem is that using Scala as a 'better java' doesn't really buy you much productivity wise. A small percentage of sub teams tried using Scala this way and hit a lot of road blocks with the unfamiliar syntax, immature tooling, and other quirks.
The teams that had huge productivity gains were the ones who leaned heavily on the functional features WHILE caring about overall readability. That means yes, we used Scalaz but we discouraged the omission of dots and parentheses (as you mentioned), discouraged operator overloading/symbolic methods, and were very deliberate about when to reach for features such as HKTs or some of the more unfamiliar features of Scalaz.
Overall it lead to a very productive and fun development experience, and at the same time illuminated many ways in which the Scala ecosystem could also be improved.
Productivity is defined in subjective terms. I know several success stories of companies that use Scala as a better Java and find themselves more productive. That doesn't mean they don't do any functional programming -- it just means they don't need to use Scalaz/cats to be happy Scala developers. The OP is mostly concerned about Scala being a language that encourages the use of monad transformers and catamorphisms all over the place. What I'm trying to illustrate is that nothing could be farther from the truth.
> This is simply not true. First, there is no Haskell influence on the language.
Since Scala has no build-in way to define FP constructs(monads, functors.. ), cats and scalaz are practically inseparable from the language itself when you try to go beyond the basics in FP. So, it is very easy to see where all the confusion is coming from
Lisp doesn't have any way to define those FP constructs and it's one of the first functional programming languages ever. I think you're being misled by Haskell.
I can't argue about Lisp. For better or worse scala fp programmers are more inspired by Haskell. Scalaz was basically an attempt to port all of Haskell to Scala, 1 to 1
We run a large (1M+ LOC) Scala codebase and don’t have these particular issues (we have other issues like bitrot in libraries but that’s the same in all languages).
You need to sort of put your foot down on using out there FP stuff like some parts of scalaz and turning your code into line noise. The non-FP parts are nice and useful though.
I can go on for days on how someone wrote some unreadable Scalaz that had atrocious performance (even with @tailrec) and someone rewrites it in plain Scala for a 100x perf win.
Still.. would I use scala again? Yes, but mainly because it allows you to use high quality Java libraries that are unmatched by any other language. It’s also just much nicer than Kotlin.
Elixir has optional parentheses but they are discouraged in most cases and the official formatter will add them back, so at least there is a community opinion.
The formatter, as Ndymium mentions, fixes a lot of this.
Optional parentheses were one of my main issues with Elixir, but once I understood why this choice was made, and what with the formatter judiciously adding them back in, I'm much happier.
(I recall having tons of issues when using the pipe operator + leaving out parentheses. Happy that these aren't much of an issue anymore.)
1. Disallow infix notation abuse through code review. Scalafmt can automate that for you.
2. I mentored a couple novice developers working on a Play codebase, the rough guideline was to use libraries that depend on Scalaz, Cats, Shapeless ... but never import any of them in our codebase. No HKT in our code either. (Nowadays I work with all that on a daily basis, you can keep things reasonable).
3. I think you're mixing up a few unrelated things. Scala's OO model is cleaner than Java's. Implicits abuse is avoidable with frameworks like Play.
Yet case classes with pattern matching and pure functions leads to some of the most readable code I’ve seen, without requiring much FP knowledge. Unlike OOP in which the logic is hidden away in some AbstractVisitorBuilderFactory and a sea of required classes to make that work.
Things can get rough when you take FP or OOP to their logical ends, the sweet spot lies somewhere in between.
* Haskell influence on the language, especially early on, encouraged the omission of dots and parentheses wherever possible. Just about every piece of sample code was written as an undifferentiated stream of tokens. There is a mental burden.
* Haskell influence on the community encourages category theory solutions to all problems. This harms interop with Java libraries, in addition to requiring a number of concepts that are safely ignored in many/most other languages.
* Scala's rich OO system (classes, interfaces, traits, singletons, case classes, implicits, etc) results in frequent design paralysis, not to mention taking a while to learn.
Elixir suffers from none of these problems, while retaining some of the things that made Scala a pleasure to use, notably the actor system of concurrency and the use of immutable data structures.