The critique about excessive and opaque operator use in libraries is fair, though I think it actually exposes an interesting philosophical issue. Scala is unabashedly written to be a flexible language. This is in opposition to Java, which was written to be a very strict language in terms of expressiveness on the part of the developer (it's perhaps the most strict of the languages I've worked with, hence it being my example). I personally think a lot of criticisms leveled against Java's verbosity and inflexibility are unfair, by virtue of the following: Many incredibly successful and complex open source projects are written in Java. While you could say this stems from Java's enormous popularity, one interesting property of huge Java open-source projects is that I can usually crack open the code and quickly get a sense of how I could contribute to the system without breaking it. While other languages often do a better job of giving me a sense of how the system works, I generally have much trouble with extensibility unless it's Java. This I believe is because Java was designed from the ground up with the goal of limiting individual developer expressivity in favor of imagining large development teams with limited cross communication.
So--I am far less anti-Java than most. But I am a big fan of Scala. Unlike Java, Scala was written to maximize developer expressivity. While writing Java can feel like putting together a legal contract, writing Scala can feel like creating a poem. I'm not making a value judgement in either direction there--I feel that poetry is a good metaphor, because things in Scala tend to fall apart in the reading department. One of the easiest things to do in poetry is to lose the reader--a great poet can put an incredibly complicated multilayered concept onto a small amount of paper--and require a graduate-level understanding from the reader to understand it. Similarly, one can very easily make Scala into an exercise in unpacking
So isn't that a bad thing? Why am I a Scala fan? Going back to my initial praise of Java--Java is so simple and predictable that it's really easy to see how the plumbing works. But because the plumbing must be laid out so meticulously and in every situation, it is often hard to see how things work at a high level. You can't see an architectural sketch in Java, you can only see endless classes in endlessly nested subdirectories. This is a very low level of abstraction, and helps the layperson (such as someone approaching a new open source project) build up an understanding from the base elements. But what's lacking is the high level abstraction.
Outside of programming languages, almost every knowledge discipline has a high level abstraction language--sometimes multiple languages. Usually the abstraction language is opaque to newcomers, and frustratingly so. Examples are the mathematical notations of various disciplines, the jargon-laden meta-language of historical theory/literary criticism, and what is popularly known as 'legalese'. But even less high falutin' fields have similar languages--listening to sports fans talking about what's happening can be quite mystifying to me, given all of the shorthand they're using. Similarly people talking about pop culture in areas I'm not familiar with.
These ubiquitous high level languages usually share two important facets: first, in a few lines of text/speech, you can pack in many books' worth of concepts. Second, unless someone has read those books, they will have no idea what you're talking about (or in the case of pop culture jargon, having spent the requisite hundreds of hours watching movies). Scala is trying to provide a language that can express the low level plumbing as Java can, but also that can express the high level meta-language. In doing so, it opens itself to the same type of criticism that mathematical notation can receive--opacity.
The pitfall, then, of Scala library developers is to create a high level meta-language (a DSL), that doesn't have industry acceptance. This is tantamount to mathematicians who create their own notation to establish proofs--such proofs can be completely unreadable to their colleagues. But this isn't a criticism that should be leveled at the idea of notation period--it's a matter of people learning to accept useful obfuscation (where jargon can reduce textual size and increase understanding) and reject useless obfuscation (inventing your own dialect of shorthand and forcing your readers to learn non-transferrable knowledge to understand what you wrote).
Because they are working with such a flexible language, and one that is targeted at building high abstraction languages, Scala library developers need to think of their audience--terseness by itself is not useful, unless you're writing throwaway code. If you're going to unleash a DSL on your reader, make sure it's in a real dialogue with the reader's expected level of knowledge with regards to how such a DSL should be structured in terms of what the symbols should mean and how they fit together.
I don't know how the Scala story will end, but I do believe that it is one of the few languages that reaches for an expressivity goal that needs to be achieved by at least some future language. Its reaching opens it to much criticism, and rightfully so, but I appreciate it for its ambition.
The poetry thing is really dead on -- when Larry Wall spoke of Perl -- he said he explicitly wanted you to be able to write poetry with it. This led to the write once, read never reputation of Perl... that Scala is quickly stealing.
Scala is on my "will not work with" list of languages/technologies -- which is generally limited to old languages/tools that I have experience with (like Progress 4GL, Mumps, etc), but don't want to touch. It is a maintainability blackhole and generally horrible (to me) to work with, despite being fairly comfortable with the core (1400 or so hours billed).
The groups I worked with made different determinations than your team, but if you guys love it, enjoy. Seriously, if you find a technology your whole team loves, you are KILLING it.
Both companies I worked with have since dropped Scala (after literally hundreds of thousands of dollars spent on the attempts) entirely internally due to maintenance and talent acquisition issues.
In my experience very little Scala code uses DSLs. Learning Scala isn't that tricky for anyone who knows Java, which is a pretty big pool.
Edit: It was two years ago so other than Lift and some SQL DSL I don't recall which libraries we were using. I do recall wishing I hadn't taken that job.
I once read an article about how Java programmers can hold a conversation on the topic of upsides and downsides of multiple dependency injection containers while C# programmers only have one available and have nothing to say on this topic. That article concluded that having one "good enough" solution can often be better than having multiple slightly different and incomplete ones, even if each has its own strenghts, and I'd say the same is true when it comes to the C# LINQ vs. Scala SQL DSLs.
The Scala equivalent is called Slick, and it's the only SQL DSL that approaching anything near widespread use. I fail to see how incomplete projects on GitHub which happen to be written in Scala are relevent to this discussion.
You are probably referring to "LINQ to SQL" which is different and significantly less popular technology than LINQ.
I too suffered a bit from DSL hell, especially some of the more extreme examples like the library "dispatch" where you need a "element lookup table" to figure out which squiggly line to use. But once you have a stable set of dependencies the initial DSL influx subsides and you start to work with a fairly manageable subset of them on a day to day basis.
Hundreds of thousands of dollars is on the order of, what, 1 engineer-year?
For example, Lisp has a simple syntax, but most people would consider infix math notation easier, although more complex.
The main downside of Groovy is: it's not as fast. And of course the programming paradigm is less revolutionary and more pragmatic, though that could also be a big upside.
In fact Kotlin looks mostly like Java with some additions to make everyone's lives easier (closures, extension methods, data classes).
Every language takes influences from others, if that's what you meant. Scala is influenced by Java, C# and Haskell, in that order. Kotlin is influenced by Scala and Java, etc.
For me and I think most other Scala devs Scala is a statically typed FP-OO language. So Haskell doesn't do it justice because Haskells insistence on purity makes it impractical for me in getting stuff done.
And Java doesn't do it justice because Java is held back by its history.
"Superset of" makes it sounds like a weakness and overwrought. In my experience it offers a sweat spot of the best features of static FP and OO.
I know this will sound snarky, but I have to ask: have you tried haskell before? I only ever hear that line of reasoning from people who have never used it (and I was once one of them, using that very same reasoning to choose a multi-paradigm language). We bailed on scala for haskell precisely because it is pure and has a better type system.
You can't say that Erik Meijer doesn't know Haskell. :-)
From the sound of it this is his first job in the "real world"? If that's the case, perhaps he just hasn't seen patterns of applying his current functional knowledge in a way thats better than the best practices from the imperative realm.
How do we know after a few years he won't switch (provided he was a fundamentalist functional programmer) back to saying "now that I have a better understanding of 'The real world' I can see patterns applied with the functional paradigm are better than the best practices I've been using from the imperative paradigm."?
I believe this is the reason to keep an ear open for authority figures, but not to take everything they say empirically, especially when it's in contradiction with a position they've held much longer.
Apologies for the rambling, I was just typing out what came to mind.
Nor is that even, I think, what I think Meijer favors. Meijir's position, from what I've seen from him in various contexts, seems to be that there are cases in real world software where the most clear expression of intent uses imperative constructs, and its better to use them -- but understand and contain their dangers -- in those cases rather than trying to avoid out of devotion to purity.
> From the sound of it this is his first job in the "real world"?
Well, if you don't count the 13 or so years at Microsoft as being "real world".I don't think he ever was a fundamentalist anything.
> I believe this is the reason to keep an ear open for authority figures, but not to take everything they say empirically
"Empirically"? Are you meaning something like "uncritically"? Because "empirically" doesn't have any meaning that makes sense in this sentence.
That's true. But I can say that he is quite happy to tailor his message to his audience, If you listen to what he is saying, he is making the argument for haskell. He is just wording it for the PHP crowd. Haskell does allow side effects, which is entirely the point. But the "unwashed masses" as it were are under the misconception that it does not. So he has to take the "side effects are awesome" sales pitch, and kinda tosses haskell under the bus in the process. Unfortunate, and ironic given that haskell programmers genuinely feel that side effects are awesome, but what can you do?
If you think scala is a superset of those, then you either really don't know scala at all, or you have an incredibly low opinion of all the languages you listed.
Just curious, what are the some languages/platforms you like or enjoy using? (Mine are Python, Erlang and Go for ex).
Shipping code: Go, Erlang, C++11 (avoiding legacy), F# (with Xamarin)
I program in many more, but those are probably my top 8 right now.
That said, I do prefer JRuby to Scala.
But in reality, when I need quick scripting, I mostly use ZSH.
I was in an odd position of having picked up 4GL and MUMPS via odd random ways when I was 19/20 -- so when everyone who used to maintain those systems vanished, I was around to step in and bill like crazy for helping them port OFF those systems onto more modern tech. Every port a MUMPS app to Erlang... I have!
Wow - that sounds like an article I'd read!
These systems are VERY different that what you are most likely used too, so having face time with them is really important.
But when I read production code it was aweful because of all the DSLs.
Scala does much to reduce code to whats necessary, like python, but there is so much more that it does, which confuses the code readability later :\
The DSLs also lead to bad API design.
The devs are always like "uhuuu if you don't like the DSL just use the normal functions" and write the horrible DSL stuff without the DSL.
(asd ~! fdd %%% sdasd) gets to asd.doSomethingRatherComplicated( with( fdd ) ).alsoGetSomeStrange( sdasd.compile() )
It looks like they are using the ability to build "easy" DSLs as excuse for bad API-design.
The next chapter delved deeper into the typing system, and I recoiled in horror.
I still want to do Scala some day just to use their actor messaging, but there really is a very strict limit to how far a sane person can look into Scala. At some point, the Abyss looks into you, and if you're not careful, you'll also start building crazy DSLs with incomprehensible operators based on Type Declarations Man Was Not Meant To Know, just to maintain rigid type safety in some situation nobody really cares about.
I've been working with Scala full-time for the past 2 years. Prior to that I worked with Perl, Python and Ruby and I still work with these languages for quick scripting or if the codebase demands it.
Scala code-bases tend to be based to a higher degree on good engineering practices. Scala itself is a much more static language than a language like Java, hence it gives you plenty of compile-time safety, with its static type system being one that helps you, instead of staying in your way. Even a tricky feature (now market as experimental SIP-18 and so they have to be explicitly enabled), like implicit conversions, is far more safer than the monkey patching that goes on in Ruby/Python, as it's lexically scoped, doesn't modify anything and the compiler throws errors if there are conflicts.
1. Lack of documentation
2. Breaking backwards compatibility
3. Opaque error messages
4. Encourages ad-hoc syntax that makes sense to one person (or team) but does not to the next -- maintenance nightmare.
5. Lack of general stability in language and libraries serving to confuse the eco-system.
Again, in my experience, the documentation in Scala land is very good. The standard library has a really good API documentation, also checkout the documentation project at http://docs.scala-lang.org/ plus there are several very good books available; then there are the libraries in Scala's ecosystem, like Play2, or Akka, or Slick for example that do have good documentation. The online documentation for Play2 does not match the online documentation for Ruby on Rails or Django, but it's newer and it's improving and I remember a time when Rails was several years old and lacked online documentation. I did find undocumented features in Play2's online documentation, but nothing that couldn't be solved with a question on its mailing list. These are open-source libraries, with strong communities that communicate a lot on mailing lists, you know.
The great thing about Scala is that you can also use any Java library you want and wrapping Java libraries in Scala-ish interfaces is actually easy and a great learning experience. I wished you'd be more explicit about this point, because for me I don't feel like there is a lack of documentation.
> 2. Breaking backwards compatibility
This is a point that comes up a lot, but I don't think it's that important for people actually using Scala. Scala is a compiled language, the libraries get distributed / deployed as compiled bytecode packaged up as Jars. This means that breaking compatibility is really easy, as all you have to do is to change an interface, like adding, removing or changing the signature of a method and boom, all code that depends on that interface needs to be recompiled, even for code that's not using the method in question. Dynamic languages that get interpreted or compiled on-the-fly, like Python or Ruby, are distributed as source-code. So by their nature don't have this disability.
The alternative to breaking backwards compatibility in Scala is to freeze the standard library. Personally that's not a compromise I want, because for this very reason Java's standard library is full of idiosyncrasies, broken interfaces, broken behaviour and various other artefacts going back to Java 1.0, that were never fixed in order to preserve backwards compatibility.
Scala has improved a lot though, compared to the 2.8 days. Nowadays you've got a guarantee that minor versions aren't breaking backwards compatibility. Code compiled with Scala 2.10.0 is guaranteed to be compatible with Scala 2.10.3 at least. The next version free to break compatibility with 2.10 is Scala 2.11. The tooling in Scala's ecosystem, like SBT, is also friendly to supporting multiple versions. To compile, test and deploy versions for multiple Scala versions is often just a configuration change, assuming you don't use APIs that aren't available in older Scala versions, in which case the back-ports are hard to accomplish in any language.
> 3. Opaque error messages
That's in the eye of the beholder. Sometimes the error messages are not so good, especially when triggered by the new macro support in Scala 2.10, but you know, those macros are experimental and improving by leaps and bounds. 90% of the time I have no problem understanding the given error messages and many times you get really helpful errors or warnings about code that you think it's correct, but isn't, like when pattern-matching on an ADT and missing a case. And I prefer opaque compile-time error messages to subtle or non-deterministic runtime error messages. In Python I used to suffer from null pointer exceptions all the time. In Scala null pointer exceptions are very rare.
> 4. Encourages ad-hoc syntax that makes sense to one person (or team) but does not to the next -- maintenance nightmare.
This is a thing that gets repeated by people that haven't used Scala, either personally or in a team. The syntax, even for libraries that go over the top on DSLs, is quite sane. It's much saner than in Ruby. And I prefer the succinctness of it, compared to code written in Java that often feels like a puke of useless crap that you have to read through in order to get to the bottom of whatever the piece of code you're reading actually does. Code written in more powerful languages feels like being harder to read, simply because each line of code does more.
It's not the syntax that's the problem dude. Having worked with Scala in a team, the real problem are the functional programming concepts involved. In Scala you end up using recursion, error-handling without exceptions (e.g. Either/Option/Try), lazyness, monads, applicative functors, iteratees or other forms of doing stream processing and the list can continue. But it's hard because most developers are not familiar with these concepts, because many of the techniques involved are like death by a thousand cuts to apply in more mainstream languages.
Then there's the type system. Scala is much more static than languages like Java or C#. It's great for users of properly designed libraries. It's not so great for language designers themselves, as people sometimes end up jumping the shark on static type safety, digging themselves into a corner. When you're seeing libraries that are hard to read because of all the generic types involved, well, on the flip side, Scala allows you to do things that are impossible to do in Java. That's why you're seeing a lot of type-casts in Java, whereas in Scala type-casts are more like an anomaly. Plus, Java uses wildcards for covariance/contravariance, which suck. Java libraries are often not generic because generic types in Java suck so badly.
> 5. Lack of general stability in language and libraries serving to confuse the eco-system.
I think at this point, you're being redundant, for the lack of better criticism. I disagree of course.
I think what I want to say is, Scala is not a mature platform. I believe the language was originally conceived to address the deficiencies of the JAVA language while retaining the versatility of the JVM as a platform.
If you look at the history of JAVA, it was a 'halfway successful attempt to drag C++ programmers towards Lisp'. Clearly this did not work well as it was not a well reasoned effort (syntax, semantics and so on) and went further downhill from the introduction of Generics in 1.5. Scala incorporates all the features of JAVA, adds halfway-to-Haskell-FP, OO-FP, XML-DSLs, some other very funky concepts stretching Generics and then...Macros...and probably stuff from JAVA 8. I humbly submit that this mixture is too much for a reasonable brain to handle. Also in the mix goes the backwards compatibility breakages. How many concepts can you cram into a semantic that in itself is not sound? Is there a standard for the language? Can I implement core Scala in C?
Scala improved a lot from previous proves that point that it is still "improving" i.e. not a mature platform as yet.
Functional programming concepts are not a problem for myself (and I believe any other reasonable programmer) it is the sensory overload of fitting it all into a model: all the language rules that you need to juggle to read a 15 line block of code that can jump between Scala, JAVA, DSL, Generics, operator overloading, etc.
Code written in more powerful languages feels like being harder to read, simply because each line of code does more...hmmm, is this a good thing? Because I have some Perl that you might wanna look at. Succinctness is power, not sensory and mental overload.
If I want the power of OO/FP/DSLs/MACROS all in one bundle, I would prefer a reasonable modern Lisp: coherence and maturity being the deciding factor in that choice.
Most of the core assumptions here, on which you base your opinion, are not correct.
For instance, Scala removes tons of crazy stuff which plagues Java.
I'm also not sure how one can add Scala's first-class OOP-FP integration as a minus. Have a look at all the other languages which only managed to do that in a lot more terrible way (F#, Java).
Generics as well. Why is the fact that scalac doesn't try and throw obstacles at you when programming with Generics bad? (Have a look at Java or C#, where tons of reasonable code is rejected by the compiler, because those compiler devs were too lazy to implement things properly.)
Same with macros. Have a look at the state of art in Java. It's a terrible mess with various black magic tools and invocations combined with poor IDE and tooling support.
If you can handle Java, I don't see an issue with Scala. Most of the stuff in Java is done in a better, more consistent and better designed way.
> How many concepts can you cram into a semantic that in itself is not sound?
I'm not seeing that at all. Care to explain?
> Scala improved a lot from previous proves that point that it is still "improving" i.e. not a mature platform as yet.
So Java is not mature, too? They are painfully adding mediocre lambda support right now. I'd call a language which was designed with lambdas in mind from the beginning and shipped with them since in 2005 more mature. The language in question is Scala.
> all the language rules that you need to juggle to read a 15 line block of code that can jump between Scala, JAVA, DSL, Generics, operator overloading, etc.
I have never seen that in practice. I often wished code written in other languages would adhere to the standards of code written in Scala. That would make things a lot more readable, maintainable and understandable.
> Is there a standard for the language?
Yes, there is.
> Can I implement core Scala in C?
Yes, why not?
> If I want the power of OO/FP/DSLs/MACROS all in one bundle, I would prefer a reasonable modern Lisp: coherence and maturity being the deciding factor in that choice.
> Maybe Clojure?
Too bad, they are currently trying to add a half-baked static type-system to core. Again, I think a language which shipped with such basic things in mind since 2003 is a lot more mature.
Which ones are not correct? What is the core philosophy of Scala?
>For instance, Scala removes tons of crazy stuff which plagues Java.
If they are removed, how can you claim efficient interop between the two? They are not removed, they are hidden/masked.
> I'm also not sure how one can add Scala's first-class OOP-FP integration as a minus. Have a look at all the other languages which only managed to do that in a lot more terrible way (F#, Java).
Anything the brings C++ inside JAVA is a minus.
>Generics as well. Why is the fact that scalac doesn't try and throw obstacles at you when programming with Generics bad? (Have a look at Java or C#, where tons of reasonable code is rejected by the compiler, because those compiler devs were too lazy to implement things properly.)
Java does not throw "obstacles" its just that the thing was not designed to handle Generics efficiently in the first place. The compiler rejects it because it is not in the spec.
>Same with macros. Have a look at the state of art in Java. It's a terrible mess with various black magic tools and invocations combined with poor IDE and tooling support.
See above, the core language spec does not have any macro facility. So what state of the art are you talking about? If you try to shoehorn it in, of course the result is black magic and poor support. And I am not too sure that macros are a 100% necessity -- Paul Graham advises sparing use of macros in your code. And he is talking about LISP code -- something that has the facility built right in.
>If you can handle Java, I don't see an issue with Scala. Most of the stuff in Java is done in a better, more consistent and better designed way.
For me, consistency means the ability to hold a reasonable model in my head. Java + Generics + OO-FP + Macros + god knows what else is not a reasonable model. Do not mistake complexity for power.
>I'm not seeing that at all. Care to explain?
Sure. Take Java syntax: If something is not designed to have a feature why do you want to try to shoehorn complex features in it? Clojure went the other way and completely changed the syntax, not mangling existing Java syntax.
Apply that to anything: the syntax, the compiler, the model, whatever.
>So Java is not mature, too? They are painfully adding mediocre lambda support right now. I'd call a language which was designed with lambdas in mind from the beginning and shipped with them since in 2005 more mature. The language in question is Scala.
I never said Java is not mature. In fact, it bends over backwards to accommodate code written in previous versions. If you want a language with lamdas built in (as an example of one feature) why not choose something that has been in existence for over 30 years, has tons of problems solved in it, was a result of original research first and commercialization later, has had more man hours thrown at its problems and implementation than Scala, etc? Why re-invent the wheel? Why not find a way of greasing the wheel better and applying a nice shine on it to make it attractive to modern programmers?
>I have never seen that in practice. I often wished code written in other languages would adhere to the standards of code written in Scala. That would make things a lot more readable, maintainable and understandable.
So all the people complaining about Scala library code readability are whiners? All code written in Scala is a lot more readable, maintainable and understandable?
Can you please point me to where the Scala specification is? It would have to be stand alone to implement in C, not built on something else. Genuine question. If there is a spec to the language (implying design and thought), why does the language keep on changing and breaking previous versions?
>Too bad, they are currently trying to add a half-baked static type-system to core. Again, I think a language which shipped with such basic things in mind since 2003 is a lot more mature.
How can an extension to something derived from decades of research lead to it being termed as not mature? Maybe they are adding it in now because the core design has proven itself -- for example after the almost effortless (conceptually speaking) porting of Go's goroutines/channels to Clojure core in the core.async extension. They had to introduce no mangled syntax and Generics for this -- to me this is elegant.
I would submit to you that nothing new comes without input from the old, and if you accept this I say Java is the wrong place to start. The JVM as a platform is awesome, the Java language is not.
Get your core model and concepts right, everything else follows.
There's this joke about how a Haskell programmer's style on a hello world programme evolves with experience, starting from a very readable, sort of down to earth implementation, and turning out in its last iteration into a complex "mess" of abstract concepts, for sensibly the same result.
It's always possible to keep things simple, even in Scala, and the opposite is also true with a language known as simple, Java, because the type system happens to be quite powerful actually. People are tempted to make things complicated also because there is this prevalent programming style in the community.
The FP model gives good tools to enable that, and encourage people to think that way.
Regarding the original topic, Scala is very much an experiental language in my opinion (because of the concepts it involves; the implementation is pretty good), so maybe there's a little bit of thruth in the article in that regard. Perhaps that's the "flaw" of academic languages. Also the comparison with Java is quite pertinent, Java being a language designed from the ground up for engineering: the grammar is fairly simple, which provided a somewhat good compromise between high readability (because of its similarities with C) and easiness at machine processing (not as easy as lisps dialect though).
I can't speak for SBT because I don't use it, but Spray is probably the nicest library for defining HTTP APIs I've ever used, in any language. As for type inference, yes it's imperfect, and maybe disappointing for someone used to Haskell, but coming from Python I found the set of type annotations I needed to add to make my Scala compile was a subset of the ones I wanted to document anyway.
Scala has unicode operators?
Also, I think you exaggerate the 'Scala is bad because DSLs' point. There are indeed a lot of libraries which overuse symbols but you are not obligated to use them. I have found the Scala I've written and read personally to be both concise and readable.
And, Scala isn't the first or the last to 'reach for the expressivity goal'. See: Haskell, Scheme, F#, & ML.
I think he meant the language that lawyers might use amongst themselves. Legalese is actually fairly low level. It's like a fully type annotated version of English that redefines all library functions each time.
I agree that it becomes tricky to get an overview of the whole project in C/Java/etc, but I very much disagree that it actually becomes easy to get that high level overview in Scala/Ruby/etc. As soon as the project becomes 'interestingly large' and full of the corner cases that comes with interacting with reality, all languages fall down here. Regardless of the level of the language, you are still communicating with a machine. I'd guess that for a mathematician who has spent most of their lives looking at equations and little time talking to people, a mathematical functional language may seem easier to read than a novel - but for most people this isn't the case.
The best way I've seen to handle this regardless of language is to have the high level overview outside of the code in a human form document describing the reason for components and not just what they are.
This is also why I prefer simpler languages (like Java or C, as you say) - they are very good at specifying exactly what is going on with little room for creativity to confuse things. We use legal contracts for a reason - imagine if our laws were written in poetry? Writing a computer program is much closer to a law than a poem as you need to limit ambiguity as much as possible and specify as many corner cases as possible to prevent undefined behavior. Plus being at a lower level means optimization strategies are easier to see.
No, it isn't really contentless.
All really complex systems will have ... well, less than perfect parts. That goes for programming languages in (at least) a subset of their use cases.
You can either live in denial of "cruft" when choosing programming language or accept that you need to enforce a standard of best practices in your group.
The overhead of designing/teaching and following those "best practices" needs to be factored into the equation too, of course. It might e.g. be too much of a pain for the std library of PHP (example chosen because I don't know PHP enough to have an opinion.)
Isn't this just a rationalization? Any unexpected behavior is by definition something the user didn't know to expect.
I worked on a large C++ project. Most code was written in a very concrete way. This lead to reams of boilerplate code which bothered me a lot. I thought it was difficult to grasp because there was so much code and there was no explanation of concepts. To me concepts are important. Instead I wrote high level but quite abstract code, but with good documentation of concepts I used.
Sadly I noticed people had big problems understanding my code. I tried to analyze why. My best explanation would be that they were not interested in software architecture like me so they could not recognize concepts and patterns as easily. Furthermore they were not used to reading documentation about concepts. They just wanted to look at the code right away. That is what they were used to. But that was hard, because my code was quite abstract.
I have no idea what the solution to this contradiction is.
Take clojure. Both very expressive and very readable.
The problem of Scala is not that it is oh so awesome and expressive. It is in a failed attempt to marry two very complex worlds: OO and FP. Of course the complexity of language explodes on unsuspecting developers.
Scala is a cautionary tale for every language creator out there. Chose carefully what you pack into your language.
There's absolutely no need to create a monstrosity like scala in order to reduce boilerplate. Even such complex language as haskell is much simpler and more readable than scala.
That's the reason both OO and FP camps reject scala. It is OVERENGINEERED.