Productivity of a programming language is a tricky bit.
Definitely you can achieve more with less characters in Scala than Java. Are you paying by the character?
For me, legibility and long term readability is the most dominating factor out of any. This is really subjective, but saving on characters you have to type, only to make the code a lot harder to read seems like penny wise pound foolish to me.
And to pull out an expert who agrees with me, Linus slaps C++ around for many of the same reasons. He noted that it's a lot easier to review patches in C because there is no hidden features (eg: operator overloading) that prevent comprehension.
I don't pay by the character but I do read by the character. I think there's a huge readability gain in having classes that fit on a single screen, which just isn't practical in Java (if nothing else, because of all the getters and setters that scala's uniform access principle lets you avoid).
I think the focus on operator overloading is misplaced; in C you might not be able to write "a + b" and have it launch some missiles, but you can write "add(a, b)" and have it launch some missiles, which is just as bad. If anything Scala is more predictable and uniform here - "a + b" is just sugar for "a.+(b)", methods and operators work the same way, and the operator precedence list you have to memorize is much shorter than C's.
In a well-designed library, it does what it looks like - whatever "~" means in the language of that domain. In a badly-designed library it could do anything. Just like .add().
(It's normal for the same symbol to mean different things in different domains, even in Java. If a and b are BigIntegers, a.add(b) means one thing; if a and b are Wicket components, a.add(b) means something quite different. Wicket remains a respected, well-designed library even though it "overloads" the word "add" in this way)
(Another reply points out that it has the same meaning on numeric types - bitwise negation - as in Java, but I doubt that's what you're asking about)
When dealing with arithmetic equations the cognitive burden of add vs + can be quite high. Not allowing the overriding of arithmetic operators means that all new mathematical code you right will be second class vs primitives, encouraging people to not use special types in math operations. This leads to unit mismatches and other sorts of bugs.
The ~ operator in scala is the same as in java (if it isn't overloaded)
Ah, but you are comparing line by line or function by function. Is a 3 line scala for comprehension doing simple mapping more 'readable' than a 10 line java loop? Well, depending on who you ask the answer is either "about the same" or "less readable" if they aren't familiar with the idiom.
However, it's pointless to compare methods when we need to be comparing applications. In my experience, I'd say I get about... 100 times reduction in LOC compared to a java application. Not hyperbole, two orders of magnitude LOC reduction compared to java applications.
Now, given that information, does it matter if each particular line takes you three times as long to read? With more type safety to boot?
I don't think anyone is criticizing for comprehensions as unreadable. Implicits in particular introduce non-local effects that may not visible from reading a particular piece of code, and in my experience should be used sparingly.
I'm curious to see how Scala matures. Right now the community is really into the FP side. So much so that they want to make everything look like Haskell. So we've got operators and types and nomenclature that doesn't make sense to the average developer. So the developers could mature/advance/become-academic or they could take the good parts of Scala and treat it as Java++. I, frankly, think the second is better.
A few years ago, this was very much true. The Dispatch lib for doing HTTP requests was particularly guilty of this - you had to learn a whole new mapping of symbols to methods!
I feel Scala is beginning to stabilize now. The recent release of 2.11 fixed several annoying issues, notably thread-safe reflection. The community is beginning to build some substantial and usable libraries. There's a still a long road ahead, though.
That being said, I doubt (and fervently hope against!) Scala will ever become Java++. Scala seems to constantly push the boundaries of language design. This is great, as it results in exposure for some lesser-known concepts into the mainstream developer community (e.g. Scala implicits ~= Ruby refinements).
With regards to language stability - the docs will specifically warn you against highly experimental features (e.g. macros), and for many you even need to explicitly import something to enable them.
The type system is very much rock-solid. Scala doesn't force you to use co/contra-variance or higher-kinded types, but they're there should you need to write very theoretically sound or extensible code.
I'm not sure if it's accurate to say that the community is on the FP side, or if there's just an extremely vocal FP community within scala drowning out all the other scala community members.
This is one of my major grips about Scala, but sometimes I'm also guilty of overusing this feature how you do Google <:< or ~?> or λ. Its even worse when the api you are working against doesn't have a "normal" function for what you are trying to do. It does take a while to remember them but even worst it makes it hard for new users to follow your code. Reminds me of some for a lack of a better work "voodoo" Perl code way back.
Yes, you're always paying the character: each character increases mental load on the developer - either through code complexity (https://github.com/scalaz/scalaz) or just the sheer amount of code (would you want to code everything in assembly?).
Leaky abstractions, as you mentioned, result in unclear code.
On the other hand, well-designed and easily understood abstractions reduce complexity.
Take for example, the atrocious lambda 'hacks' needed before Java 8 - create an anonymous class, then override a method. Compare that with something like words.map { _.size }
People think in terms of hierarchy and concepts, not individual components. For example, cars with more internal components are not actually more difficult to DRIVE than simpler cars (eg: carburetor vs fuel injection).
Likewise, people don't pay by the character. They pay by the word. They also pay by the concept, so having N different ways to do something simple can be a higher cognitive burden than just 1 way. (hence python vs perl).
Now, I believe that clear code, "well designed" code (despite the fact that its patently obvious that no one agrees on what well designed actually MEANS) are better. Good abstractions.
But these are a function of the programmer from which they come from. The programming language makes a difference but I'm starting to suspect beyond a certain point of feature completeness, you are hitting diminishing returns then negative returns. Yes Java8 has Lambdas, that helps a lot. But would Java9 benefit from implicit parameters? Or from nearly any punctuation being an operator that can be overridden? I argue these 2 features of scala, which people love for their ability to build concise, hard to read, harder to write, DSLs are part of the problem.
Ok enough ranting. My parting shot is I write a 25,000 lines of scala into a production system. We had to rewrite ALL the for loops into while loops. In the end, I'd say Scala was generally helpful but not so much that I'd do it again.
It's unarguably shorter than anything you could write in most other languages, but is it more readable?
My point is that, while too many characters are bad, too few are bad as well. And that possibly the "just right" verbosity varies from person to person. And also that readability is completely unresearched topic without any established facts we could argue about... Anyway, the key takeaway: we're all wrong on the issue of readability and we don't even know how much wrong.
This is such a strawman. I really doubt that there are a lot of people who favour terse programming languages (or programming practices) only because of how little they have to write - if that was the only concern, they would be happy with a verbose language as long as it had good support for autocomplete and boilerplate generators.
Some people think that terse code is more readable, not just more writeable.
Comments
Productivity of a programming language is a tricky bit.
Definitely you can achieve more with less characters in Scala than Java. Are you paying by the character?
For me, legibility and long term readability is the most dominating factor out of any. This is really subjective, but saving on characters you have to type, only to make the code a lot harder to read seems like penny wise pound foolish to me.
And to pull out an expert who agrees with me, Linus slaps C++ around for many of the same reasons. He noted that it's a lot easier to review patches in C because there is no hidden features (eg: operator overloading) that prevent comprehension.
I don't pay by the character but I do read by the character. I think there's a huge readability gain in having classes that fit on a single screen, which just isn't practical in Java (if nothing else, because of all the getters and setters that scala's uniform access principle lets you avoid).
I think the focus on operator overloading is misplaced; in C you might not be able to write "a + b" and have it launch some missiles, but you can write "add(a, b)" and have it launch some missiles, which is just as bad. If anything Scala is more predictable and uniform here - "a + b" is just sugar for "a.+(b)", methods and operators work the same way, and the operator precedence list you have to memorize is much shorter than C's.
Humans read by the word, not by the individual letters. + vs add() is not a real cognitive burden.
Btw what does the operator ~ do in scala?
In a well-designed library, it does what it looks like - whatever "~" means in the language of that domain. In a badly-designed library it could do anything. Just like .add().
(It's normal for the same symbol to mean different things in different domains, even in Java. If a and b are BigIntegers, a.add(b) means one thing; if a and b are Wicket components, a.add(b) means something quite different. Wicket remains a respected, well-designed library even though it "overloads" the word "add" in this way)
(Another reply points out that it has the same meaning on numeric types - bitwise negation - as in Java, but I doubt that's what you're asking about)
I'm not sure what you mean by word, but + vs. add() definitely have different levels of cognitive burden:
Compare: (a + (b + c)) + d vs. add(add(a, add(b, c)), d)
One is arithmetic, the other is polish notation.
Even polish notation benefits from +, IMO.
+ + a + b c d
We can also (with mainstream OO syntax) make add infix and it's still ugly:
a.add(b.add(c)).add(d)
Yuck, really? I find that much less readable than "add(add(a, add(b, c)), d)"
shrug I've probably done more rpn. A huge component of "readable" is "how similar is it to stuff I am used to reading".
I do have to read it backward and build the stack, but that's basically intuitive at this point.
When dealing with arithmetic equations the cognitive burden of add vs + can be quite high. Not allowing the overriding of arithmetic operators means that all new mathematical code you right will be second class vs primitives, encouraging people to not use special types in math operations. This leads to unit mismatches and other sorts of bugs.
The ~ operator in scala is the same as in java (if it isn't overloaded)
Ah, but you are comparing line by line or function by function. Is a 3 line scala for comprehension doing simple mapping more 'readable' than a 10 line java loop? Well, depending on who you ask the answer is either "about the same" or "less readable" if they aren't familiar with the idiom.
However, it's pointless to compare methods when we need to be comparing applications. In my experience, I'd say I get about... 100 times reduction in LOC compared to a java application. Not hyperbole, two orders of magnitude LOC reduction compared to java applications.
Now, given that information, does it matter if each particular line takes you three times as long to read? With more type safety to boot?
I don't think anyone is criticizing for comprehensions as unreadable. Implicits in particular introduce non-local effects that may not visible from reading a particular piece of code, and in my experience should be used sparingly.
I'm curious to see how Scala matures. Right now the community is really into the FP side. So much so that they want to make everything look like Haskell. So we've got operators and types and nomenclature that doesn't make sense to the average developer. So the developers could mature/advance/become-academic or they could take the good parts of Scala and treat it as Java++. I, frankly, think the second is better.
A few years ago, this was very much true. The Dispatch lib for doing HTTP requests was particularly guilty of this - you had to learn a whole new mapping of symbols to methods!
I feel Scala is beginning to stabilize now. The recent release of 2.11 fixed several annoying issues, notably thread-safe reflection. The community is beginning to build some substantial and usable libraries. There's a still a long road ahead, though.
That being said, I doubt (and fervently hope against!) Scala will ever become Java++. Scala seems to constantly push the boundaries of language design. This is great, as it results in exposure for some lesser-known concepts into the mainstream developer community (e.g. Scala implicits ~= Ruby refinements).
With regards to language stability - the docs will specifically warn you against highly experimental features (e.g. macros), and for many you even need to explicitly import something to enable them.
The type system is very much rock-solid. Scala doesn't force you to use co/contra-variance or higher-kinded types, but they're there should you need to write very theoretically sound or extensible code.
I'm not sure if it's accurate to say that the community is on the FP side, or if there's just an extremely vocal FP community within scala drowning out all the other scala community members.
Perhaps that is true. But they seem to be in API vanguard.
This is one of my major grips about Scala, but sometimes I'm also guilty of overusing this feature how you do Google <:< or ~?> or λ. Its even worse when the api you are working against doesn't have a "normal" function for what you are trying to do. It does take a while to remember them but even worst it makes it hard for new users to follow your code. Reminds me of some for a lack of a better work "voodoo" Perl code way back.
Yes, you're always paying the character: each character increases mental load on the developer - either through code complexity (https://github.com/scalaz/scalaz) or just the sheer amount of code (would you want to code everything in assembly?).
Leaky abstractions, as you mentioned, result in unclear code. On the other hand, well-designed and easily understood abstractions reduce complexity.
Take for example, the atrocious lambda 'hacks' needed before Java 8 - create an anonymous class, then override a method. Compare that with something like words.map { _.size }
People think in terms of hierarchy and concepts, not individual components. For example, cars with more internal components are not actually more difficult to DRIVE than simpler cars (eg: carburetor vs fuel injection).
Likewise, people don't pay by the character. They pay by the word. They also pay by the concept, so having N different ways to do something simple can be a higher cognitive burden than just 1 way. (hence python vs perl).
Now, I believe that clear code, "well designed" code (despite the fact that its patently obvious that no one agrees on what well designed actually MEANS) are better. Good abstractions.
But these are a function of the programmer from which they come from. The programming language makes a difference but I'm starting to suspect beyond a certain point of feature completeness, you are hitting diminishing returns then negative returns. Yes Java8 has Lambdas, that helps a lot. But would Java9 benefit from implicit parameters? Or from nearly any punctuation being an operator that can be overridden? I argue these 2 features of scala, which people love for their ability to build concise, hard to read, harder to write, DSLs are part of the problem.
Ok enough ranting. My parting shot is I write a 25,000 lines of scala into a production system. We had to rewrite ALL the for loops into while loops. In the end, I'd say Scala was generally helpful but not so much that I'd do it again.
Not so. A quicksort in J is one absolutely lovely counter-example:
It's unarguably shorter than anything you could write in most other languages, but is it more readable?My point is that, while too many characters are bad, too few are bad as well. And that possibly the "just right" verbosity varies from person to person. And also that readability is completely unresearched topic without any established facts we could argue about... Anyway, the key takeaway: we're all wrong on the issue of readability and we don't even know how much wrong.
This is such a strawman. I really doubt that there are a lot of people who favour terse programming languages (or programming practices) only because of how little they have to write - if that was the only concern, they would be happy with a verbose language as long as it had good support for autocomplete and boilerplate generators.
Some people think that terse code is more readable, not just more writeable.