It's less true now because some of the patterns associated with code that's difficult to understand have been deprecated or flagged by the community to avoid.
For example, implicit conversions are now disabled by default. It's possible in Scala to pass a Foo to a function requiring a Bar due to a chain of automatic conversions from Foo -> Baz -> BazMutable -> Bar. This is fun and magical but difficult to understand and debug. The community and language itself now suggests against this pattern.
Another example is that it's now (more or less) recognized within the community that it's not preferable to dogmatically adhere to a particular style of programming, such as pure functional or reactive/actors. It's better to use the right tool for the right problem.
Whole classes of confusing code are now prevented or mitigated by language changes in Scala 3. For example, Scala 2's implicits are famously hard to learn and follow within a codebase. One reason for this is that in Scala 2 the keyword "implicit" was overloaded into a few common patterns, including the aforementioned implicit conversions, typeclass instances, and dependency injection. Scala 3 introduces new constructs and keywords to split out these patterns into separate language features, making them easier to learn and more understandable within a codebase.
> For example, implicit conversions are now disabled by default. It's possible in Scala to pass a Foo to a function requiring a Bar due to a chain of automatic conversions from Foo -> Baz -> BazMutable -> Bar. This is fun and magical but difficult to understand and debug. The community and language itself now suggests against this pattern.
Oh God I'm having flashbacks to using Lift in... 2012? There were about four levels of implicit conversions between my model and the final JSON, trying to understand that was hard.
That said, David Pollak the founder of Liftweb was amazingly helpful on on their mailing list.
> For example, implicit conversions are now disabled by default. It's possible in Scala to pass a Foo to a function requiring a Bar due to a chain of automatic conversions from Foo -> Baz -> BazMutable -> Bar. This is fun and magical but difficult to understand and debug. The community and language itself now suggests against this pattern.
I don't have experience with Scala 3 or Scala 2.13, but I don't believe this is true. Implicit conversions cannot be applied more than once.
Haha, I thought it was only me who thought this way :) I did enjoy learning Scala. It expanded my horizon. And, I enjoyed coding in it.
The code written by experts were at a whole another level. Couldn't make much sense of them. Maybe I could understand one line at a time, but the design patterns appeared hard to understand after my ~12 months Scala experience and over a decade of programming.
That said, the expert code looked amazingly beautiful :)
Since the syntax didn't (and cannot) become any less flexible, it's unfortunately still true and always will be. As annoying as it is to struggle with the rigid syntax of Java while writing it (which also results in overly verbose code), reading it is far easier than Scala (or even Kotlin in some cases), because Java code always looks like Java code.
And since we spend way more time looking at and interpreting other people's code than writing our own, personally I think Java is better for large projects. I wish it wasn't the case but it is.
For example, implicit conversions are now disabled by default. It's possible in Scala to pass a Foo to a function requiring a Bar due to a chain of automatic conversions from Foo -> Baz -> BazMutable -> Bar. This is fun and magical but difficult to understand and debug. The community and language itself now suggests against this pattern.
Another example is that it's now (more or less) recognized within the community that it's not preferable to dogmatically adhere to a particular style of programming, such as pure functional or reactive/actors. It's better to use the right tool for the right problem.
Whole classes of confusing code are now prevented or mitigated by language changes in Scala 3. For example, Scala 2's implicits are famously hard to learn and follow within a codebase. One reason for this is that in Scala 2 the keyword "implicit" was overloaded into a few common patterns, including the aforementioned implicit conversions, typeclass instances, and dependency injection. Scala 3 introduces new constructs and keywords to split out these patterns into separate language features, making them easier to learn and more understandable within a codebase.