I really disagree with the author in terms of metaprogramming. One thing in particular jumps out at me:
> Ultimately, a programming language that's useful for large-scale programming projects needs to have clear, unambiguous grammar and syntax so that any developer familiar with the project and the language can instantly figure out what's going on.
Wow. There are just so many things wrong with this statement. Let me enumerate them:
1. Scala does have a clear, unambiguous grammar. If it didn't there wouldn't be a Scala compiler. I think what the author means to say is that languages need to have less flexible grammars (like Java does).
2. Just because you can use all kinds of wild things to obscure your code doesn't mean you should. If you prefer the "boring" way of doing something, then go for it. You just have to understand that just like anything else in programming, it's about tradeoffs. Does the benefit gained from using a DSL or operator overloading outweigh the costs? Sometimes it does, sometimes it doesn't.
3. The idea that a programmer (even one who's familiar with a project) can look at any given piece of code and instantly understand what's going on is a myth. Even if that snippet of code makes perfect sense, you also need to understand the state the program is in before that piece of code executes. Again, it's about tradeoffs. You need to choose the method that allows programmers to understand code more quickly. Sometimes using metaprogramming is the way to do that.
I will grant the author that there are valid reasons not to choose Scala, but I don't think he's hit them.
Regarding 1, there are languages that do not have a clear, unambiguous (to my reading, formalized) grammar yet possess compilers. Examples include classical FORTRAN, Forth and (if I'm feeling particularly trollish today) C++.
I would disagree with your point 3. Sufficiently well written code (by which I mean deliberately written in a clear style with good comments) is readable right off the bat.
What you want to avoid is invisible side-effects. Aspects for instance have their place, but if someone has tried to be too clever for their own good the program may be breaking in a way that is completely invisible when you look at the code.
No code is readable right off the bat. I mean you need to see it (meaning look at it in your editor), piece it together in your brain, and then place it in the context of the rest of the code. Of course, that doesn't sound like a big deal, but it adds up.
Some code might be readable more quickly but again, it's about tradeoffs. To take an extreme example, suppose the "instantly" readable method results in 10000 lines of code while the metaprogramming approach takes 10 lines. Clearly, even with extra levels of indirection the metaprogramming approach is more easily understandable by sheer virtue of there being less code.
Again, that's an extreme (and unlikely if not impossible) case, but it illustrates my point: it's all about tradeoffs.
If your code isn't readable right off the bat, you're doing it wrong.
At one place I worked I had a BA who was nosey and came and tried looking over my shoulder at one point at some file manipulation code I'd written. Now I used to put a lot of time and effort into writing nice neat code, but this was something for me alone, so I hadn't bothered putting in the comments that I normally would.
Anyway, because I wanted him to take a hike, I thought, "right, let's call his bluff". So I asked him whether he understood what the code was doing. And he said yes. Frankly, I didn't believe him, so I asked him to say what it was that the code was doing, and you could have knocked me over with a feather when he was able to run down the page of code and say pretty much what everything there did.
Another example: I often hear people say that they can't read the code they wrote 6 weeks ago let alone 6 months ago. I can.
Now, I'm not suggesting that everyone has to go out and start writing code that even non-programmers can read, but there are a couple of guidelines:
(a) pick good variable names
(b) pick good method names
(c) pick good class names
(d) whitespace is more important than you think (as is indentation)
(e) only do one thing per line if you can help it
(f) the one line of super-cunning code that replaces two lines of boring mundane code that does exactly the same thing may actually run slower after the JIT and other optimisations
(g) the easier it is to read, the easier it is to debug
(h) debugging is expensive, really expensive, much more expensive than writing the code in the first place, hence any investment in readability will almost immediately pay dividends
(i) code unto others as you would have them code unto you
I think there's a confusion of micro- and macro-readability in this thread. You are describing micro-readability, IMO. I've read lots of code where it was clear what each line of code did, but not at all clear what the end result was, or why it was being done.
Furthermore, there's dramatic disagreement about what is actually more readable. I have an ongoing debate with a coworker about the relative readability of
widgets.each |w|
return true if w.can_frobnicate?
end
return false
vs
widgets.any?(&:can_frobnicate?)
He insists he can read the first faster and more easily than the second. My contention is that he isn't actually reading the first, but performing a visual pattern match and guessing what it does. I've actually found examples where this seemingly-trivial idiom is implemented incorrectly, which I think supports that claim.
At any rate, though, as long as readability is subjective, I think all the rest of this debate is in question.
"You are describing micro-readability, IMO. I've read lots of code where it was clear what each line of code did, but not at all clear what the end result was, or why it was being done."
No. Unless you consider chunks of 90-100 lines of code to be micro, in which case I think your point is irrelevant, you have effectively defined the terms of the debate such that you've argued yourself right out of it. Also, your terms are silly, if looking at 100 lines of code is micro, what is macro? Looking at 10,000 lines of code simultaneously? you must have a very generous boss to have bought you such a large monitor!!!
The test of readability which I administered was at the unit level, not the individual line of code level.
I think you make a good minor point about why. The why is incredibly important. This is something that people who say they don't bother with comments because comments get out of date blah blah blah get wrong. A comment is not there to say what you are doing, a comment is there to say why you are doing it, or what you want to achieve. Also, comments should be kept up to date. It costs practically nothing to slip in a:
// bugfix for bug #127; forgot to snorgle the barr
it's certainly a little syntactically ugly. I'd much prefer it if functions were first-class and I could write something like "widgets.any? can_frobnicate?" or "any widgets can_frobnicate?".
> Ultimately, a programming language that's useful for large-scale programming projects needs to have clear, unambiguous grammar and syntax so that any developer familiar with the project and the language can instantly figure out what's going on.
Wow. There are just so many things wrong with this statement. Let me enumerate them:
1. Scala does have a clear, unambiguous grammar. If it didn't there wouldn't be a Scala compiler. I think what the author means to say is that languages need to have less flexible grammars (like Java does).
2. Just because you can use all kinds of wild things to obscure your code doesn't mean you should. If you prefer the "boring" way of doing something, then go for it. You just have to understand that just like anything else in programming, it's about tradeoffs. Does the benefit gained from using a DSL or operator overloading outweigh the costs? Sometimes it does, sometimes it doesn't.
3. The idea that a programmer (even one who's familiar with a project) can look at any given piece of code and instantly understand what's going on is a myth. Even if that snippet of code makes perfect sense, you also need to understand the state the program is in before that piece of code executes. Again, it's about tradeoffs. You need to choose the method that allows programmers to understand code more quickly. Sometimes using metaprogramming is the way to do that.
I will grant the author that there are valid reasons not to choose Scala, but I don't think he's hit them.