Death of a Language Dilettante(prog21.dadgum.com) |
Death of a Language Dilettante(prog21.dadgum.com) |
1. Easy to write/produce: Languages/Framework that are easy to write because they are highly expressive (Haskell/Scala) or are very opinionated (Rails).
2. Easy to read/maintain: Verbose languages with excellent tools... cough... Java/C#.
As for reading code I don't know what it is about crappy verbose languages but I have yet to see Java/C# code that I couldn't figure out what was going on. Sure I have more experience with these languages and the tools (particularly code browsing with an IDE) make it so much easier... but so do most people.
The reality is language dilettantes think writing code is painful (as mentioned in the first paragraph by the author) but the real bitch is maintaining.
I feel like there must be some diminishing returns on making a language too expressive, implicit, and/or convenient but I don't have any real evidence to prove such.
The pitfall with #1 is leaky and obscure abstractions. It's easy to write code that has performance problems or requires a lot of understanding of moving parts not actually related to the problem at hand. Where's the code responsible for putting the current state on a web page? All I see is a bunch of monad transformations and I don't know what they're for! Sure, I can figure out what's going on eventually, but I'll have to read a lot of CS papers first.
The pitfall with #2 is lack of ability to write a suitable abstraction for the problem. Instead, the problem has to be fit to the language. You end up with either something relatively simple, but inflexible or a large amount of incidental complexity. Why do I need to implement AbstractThingPutterOnPageGenerator and generate a ThingPutterOnPage before I can put a thing on the page? Couldn't this just be called putThingOnPage() and use some optional args when the default behavior doesn't cut it? Sure, I can figure out what's going on eventually, but I'll have to read a lot of code first.
I think Lisp has always been strong in the third category, and that Clojure is a Lisp especially suited to real-world use right now. The heavy emphasis on defining code in terms of generic operations on generic data structures is a particular strength. For something more mainstream, Python does pretty well here. That's largely cultural though; Python has a very comparable feature set to Ruby, but Ruby's community doesn't have "explicit is better than implicit", the lack of which can lead to code which is impenetrable rather than merely dense.
I think it is understood that the more expressive your language is, the more difficult it is to make tools for the language. For example, Common Lisp style (non-hygienic) macros are hard to support in a debugger (by which I mean, hard to allow the developer to step through their code as they wrote it, rather than stepping through the final expanded form). Dynamic dispatch makes it difficult for tools to provide who calls and which function does this call invoke (not impossible, with some forms of static typing, but more difficult in general).
It seems with really expressive languages you get programmers who will use extremely short variable/function names (Haskell being the extreme). Of course this could be just cultural (e.g. Haskell academia). That is it seems when the language gets easy people get lazy :) (this is probably a false assumption).
I'm not sure if its analogous but an extreme opposite of expressive language would be punch cards. My grandmother used to work on ancient computers and you would have to really think ahead what you wanted to do. Consequently lots and lots of documentation would be done.
There's the cognitive load of the language itself. There's the cognitive load of the libraries. There's the cognitive load of the algorithm. And there's the cognitive load of the actual code (number of lines times how hard each line is to read - smart coding conventions help quite a bit here).
But it's not that simple, because people are different. Different people have different cognitive load when presented with the same language. I think this is one of the reasons Haskell is so polarizing - it either has a low cognitive load for you, or a very high one. And if it has a very high one, you're not likely to spend the time and effort to get to the point where it has a low cognitive load for you.
> I feel like there must be some diminishing returns on making a language too expressive, implicit, and/or convenient but I don't have any real evidence to prove such.
I think that going to far in any of those directions probably increases total cognitive load, by making some other component worse.
The problem was not with the languages themselves, they are just fine, and I actually quite like C# -- but it seems that a lot of third-party library authors for these languages really go all out on various design patterns, abstracting everything, etc., in the process making simplest things quite impenetrable.
Could have been just my luck though.
The problem with these assumptions is that you don't run into situations like that often. You're far more likely to run into a team of people of mixed abilities, and with some languages, one or two of them will be able to inflict horrors on the whole codebase.
WTF, I haven't heard that one before. Did you make it up?
When I google it, your above comment is the third hit, and the previous two aren't relevant.
The general observation that either the tool or the operator can be improved in an operator-tool system is semi-regularly invoked in discussions of new programming languages/EDC multi-tools/governance models within my conversational circles.
[0] https://www.reddit.com/r/systema/comments/3lcn5q/systema_lin...
Which human language? The one spoken by the people you need to communicate with is most valuable.
The first iPhone? Very valuable then; not today.
But some people love intrinsic value. And it's what they create that ends up having real value. They would say that intrinsic value is the only "real" value. They aren't very practical.
In the short term practical concerns can be more important than PLT ones - in five years' time I'm sure Idris will be a better language than Scala, but for some tasks it isn't yet - apart from anything else, you need a strong library/tool ecosystem before a language is truly useful. But that's a temporary state of affairs. If you were making this kind of judgement 20 years ago, and chose a popular language like Perl or TCL or C++ over a theoretically-nice language like OCaml or Haskell, how would you be feeling about that decision today?
Every developer should be forced, I believe, to read Arthur C. Clarke's story Superiority ( https://en.wikipedia.org/wiki/Superiority_%28short_story%29 ) and to reflect on its application to their profession.
EDIT: Story can be found here... http://www.mayofamily.com/RLM/txt_Clarke_Superiority.html
Well worth a few minutes. Not that teaching it would help much, wisdom rolls off people's minds like water off a duck's back.
It also leaves out another reason for learning languages and using them for pet projects: it makes you a better programmer. The more good languages you know, and idioms from those languages, the more likely you are to recognize when an ad-hoc implementation of one of those idioms is the right solution to a problem in the language you're actually using.
[0] Though possibly only as a compilation target.
Take a look at this example - http://blog.fogcreek.com/the-origin-of-wasabi/
A language that compiles to PHP and ASP, what a relief.
And for the contemporary result - http://blog.fogcreek.com/killing-off-wasabi-part-1/
When the platform catches up, then you can go back to mainstream development with a useful language.
No, it hasn't been stopping them, but I guarantee you it's been slowing them down, at least a little. If nothing else, it makes the language a little bit harder to learn than it needed to be. I'll wager it also causes actual bugs that people have to spend time tracking down. It's true that those bugs can be avoided by proper discipline, but the brain cells required for enforcing that discipline could have been used for something else.
ETA: I agree with the author that a certain pragmatism is useful in selecting a language for a particular project, but I still think it's important to raise people's consciousness about warts in language designs. Doing so improves the odds that the next language someone designs to scratch their personal itch, but that happens to catch on for some reason, will have fewer such warts.
Async bugs, on the other hand, were nightmarish at times.
Is it harder to learn a smaller thing with some tricks than a larger thing with few tricks?
Those are two questions I often ask myself when thinking about the evolution of the JS ecosystem.
then i moved on to languages that allow binding function to variable. i had much less files. simpler.
FP with anonymous function further frees my mind from naming variables so i have zero chance of mistyped function names. easier maintenance? sure
those didn't stop me from getting work done; however, i prefer to not waste time on weaker programming languages, although coding on those languages did broaden my mind (yeah, now i know they suck)
Also misses the point, it's not the job at hand that matters, it's the 10000 jobs that keeping the thing alive that matters.
There are lots of Java jobs, yes, but there are also lots of Java programmers too. I'm a python dev (now) and while I have to search a little longer for jobs, I get good pay still, since I'm also rarer.
Indeed. Using a different definition of "strong work ethic", I've met programmers who had too strong a "work ethic" - using it as an excuse or crutch to scoff at improvements to code readability or maintainability. After all, if you just power through it with enough overtime, you can wade through even the worst codebases, so why bother cleaning it up? To make things easier? And you want to take a break to step back, think on the problems, and discuss options instead of just sitting down and coding more? Sounds like you're just looking for excuses to be lazy - put down the coffee and get back to work!
Needless to say, this can lead to a lot of firefighting and damaged morale.
Ivory tower academics can get too caught up on theory to practice effectively. On the other hand, that's probably still preferable to the COBOL-only programmer that doesn't understand why things have changed since the 1970s - after all, COBOL can do anything your newfangled languages can! Better than either: Give me a practical polyglot. Preferably one who hates whatever terrible language we're going to be using, with a laundry list of issues that language has to back up that hate. Why such a hater? Because that hate sounds like the impassioned voice of experience with these problems (and how to mitigate or avoid them, even if one of those options - switching languages - isn't on the table.)
That's not to say you can't bring new technologies into a company. I've done it several times. You just need to understand that it's a big undertaking to get an entire team to buy in and learn that new tech.
Of course for hobby projects, go hog wild. That's how I pick up new languages.
Thing is, this is a testable hypothesis (at least in theory): measure whether those "intrinsically valued" languages make a true impact on software cost. Often, it is the very same people who tout this intrinsic value who deliberately shy away from testing this hypothesis empirically.
It's interesting that when Java's original designers analyzed customer needs vs. features offered by academic languages, they discovered that most value in those languages wasn't in the linguistic features but in the extra-linguistic features, so they deliberately put all the good stuff in the VM, and packaged it in a language designed to be as unthreatening and as familiar as possible. It was designed to be a wolf in sheep's clothing:
It was clear from talking to customers that they all needed GC, JIT, dynamic linkage, threading, etc, but these things always came wrapped in languages that scared them. -- James Gosling[1]
Value types would be helpful to a serialization algebra I've worked on.
I can google this, but since this 2014 talk, do you know the real world adoption of java lambdas, and actual performance benefits of their parallelism? I really liked Steele's re-tree idea, but doesn't seem to have that much benefit. Of course, if no dependencies between data, speed up should be great). The real issue is performance is mostly not an issue - hence python/ruby success.
I agree, but how did customers need JIT? I thought it was just to compensate for the inherent performance penalty of an extra layer, of a VM.
BTW: Android java now uses ahead-of-time compilation (5.0 switched from JIT dalvik to AOT art).
Just on the "wolf" part: not only was the language familiar (sheep's clothing), but features were removed. Not just for familiarity, they actually caused problems and so removing them was an improvement.
e.g. removing operator overloading (which C++ had): apart from very fundamental maths (such as complex numbers and matrices), these caused a lot of problems. Probably because they were algebras designed by non-mathematicians. Removing them hurt matrix algebra etc, but was by far a net benefit. (BTW a nice thing about shader languages is matrices as first class values).
Finally, taking this back to my GP comment on intrinsic vs extrinsic: I was thinking of the language as a "product" which would include the VM... but I think your approach is better. Along those lines, performance, bugginess, portability of the runtime etc are also non-linguistic features, strictly speaking.
Actually testing that hypothesis is really difficult. I've only heard of a few attempts to measure productivity in different languages, and their experimental design is not very compelling. Of course, in practice, all those non-linguistic factors dominate.
Yet, some of James' non-linguistic "wolf" features have linguistic counter-points: e.g. no memory management; threading. Therefore, they are examples of linguistic features with "intrinsic value". I'd also include references (instead of pointers), and array-bounds checking (um... is that last one a "linguistic" feature?)
I think some language features have real value - though, as with java's inspirations, probably not the whole language, just particular features.
[ But I meant by my statement, that these folks think intrinsic value is the only "real" value, that they dispute extrinsic value entirely! i.e. that ideas are eternal, valuable absolutely and despite context; and contingent fluctuations in supply and demand, progress of technology and install base etc are 100% meaningless.
Like the truth of a theorem, regardless of its usefulness. ]
> in five years' time I'm sure Idris will be a better language than Scala
Idris? In the entire history of computing there has been a single[1] complete non-trivial (though still rather small) real-world program (CompCert) written in a dependently typed language. Even though the program is small and the programmer (Xavier Leroy) one of the leading dependent-type-based-verification experts, the effort was big (and that's an understatement) and the termination proofs proved too hard/tedious for him, so he just used a simple counter for termination and had a runtime exception if it ran out. Idris is a very interesting experiment, I'll give you that. But I don't see how anyone can be sure that it would work (although you didn't say it can work, only that it would "be a better language than Scala", so I'm not sure what your success metrics are).
[1]: Approximately, though I don't know of any other.
Seems we have a true disagreement.
> Idris? In the entire history of computing there has been a single[1] complete non-trivial (though still rather small) real-world program (CompCert) written in a dependently typed language.
Five or ten years ago how many such programs were there in a language with higher-kinded types? Thirty years ago how many with type inference? Innovation is slow - perhaps five years was too optimistic, looking at the history - but it does happen; PLT ideas do eventually make their way into mainstream languages.
> although you didn't say it can work, only that it would "be a better language than Scala", so I'm not sure what your success metrics are
I think it will be the most effective (for real-world problems) general-purpose programming language - a spot I think Scala currently holds. Hard to define objectively of course.
Did you mean that Lisps are dynamically-typed? That's true, and whether it's mostly good or mostly bad is a religious topic that almost certainly lacks one true answer. My own take on it is that I program very interactively and static typing feels like an impediment to that most of the time. Furthermore, type errors are usually a small subset of the possible errors and many static type systems allow any type to be null anyway, drastically reducing the benefit.
Several type systems.
In my view, the discussion should be about comfort. At what abstraction levels will we work? If you put in a lot of safeguards, you can work comfortably at a certain level. But if you want to move out of this band, be it to write some low-level glue-code, or some higher abstractions, you find the safeguards to be a barrier. If those safeguards are conventions, you can agree to break them, if they are laws, you must subvert them or not work at those levels.
I prefer conventions as much as I prefer working with reasonable people. And sometimes turning conventions into law has few downsides, like with the private keyword.
Edit: fixed stupid grammatical mistake
As to language effectiveness, I can't argue with you because neither of us has any real data, but I can say that there's a lot of religion surrounding the question of how much linguistic features (as opposed to extra-linguistic ones, like GC) actually increase productivity. What is certain is that we still haven't broken the 10x productivity boost Brooks said wouldn't happen between 1986 and 1996, and it's been thirty years -- not ten -- and it seems like we won't do it in another decade.
Totality is a philosophy; you can have dependent types as a feature without it. Maybe immutability or purity are better comparisons for what Idris brings to the table, but if you're just talking about dependent types then I'm using them already.
> the percentage of real-world programs using HM type-systems (and similar) has hardly changed in the past two or even three decades.
Is that really true? I can't imagine a recruiter asking about Haskell, or a Facebook-sized company talking about their OCaml strategy, ten years ago.
> As to language effectiveness, I can't argue with you because neither of us has any real data, but I can say that there's a lot of religion surrounding the question of how much linguistic features (as opposed to extra-linguistic ones, like GC) actually increase productivity.
That feels like gerrymandering your definitions to me. GC is usually a language-level feature.
> What is certain is that we still haven't broken the 10x productivity boost Brooks said wouldn't happen between 1986 and 1996, and it's been thirty years -- not ten -- and it seems like we won't do it in another decade.
How would we tell? The productivity of the technology industry as a whole has certainly risen enormously. My general impression is that coding is the bottleneck a lot less often - even for a technology company - than it was five or ten years ago.
I think it may have risen a tiny bit but here's why I think it appears larger than it is: I don't think a recruiter would ask about Haskell today outside a very small section of the ecosystem, but that section seems just larger than it is. What has changed in the past 20 years is the cultural prominence of the startup culture (SV startups hardly make up a minuscule percentage of the software industry, yet they get a significant portion of the media coverage), and even then only if you're involved in communities like Reddit and HN.
I think it is more an artifact of those communities that using certain languages lends a certain prestige, which is then used as a marketing effort (the CTO of a well known SV startup once told me that they have a small team using Scala only so they could attract a certain crowd). Similarly, in Facebook, it is my understanding that Haskell isn't really spreading, but is more of a marketing gimmick to developers of a certain sort in an environment with very unique characteristics. The entire software development industry consists of, I'd make an educated guess, 20 million developers or more (extrapolating from the known number of ~10M Java developers). I would be immensely surprised if more than a million of them can tell you what Haskell is (and by that I mean "a pure functional language").
So there's definitely an uptick in numbers and a rather strong uptick in exposure -- assuming you're following the right online communities -- but I don't think there's a real uptick in portion of production systems. Some people used Lisp and ML in production 20 years ago, too. They just didn't have HN to tell everyone about it. I'm not even sure we're currently at '80s level. Haskell is certainly talked about and used less than Smalltalk in the '80s, and see where it is today.
What is definitely true that some ideas that had previously been associated with functional programming, most notably higher-order functions, have now finally made it into nearly all mainstream languages.
> That feels like gerrymandering your definitions to me. GC is usually a language-level feature.
I think the distinction between language-level abstractions and something like a GC (or dynamic linking) is rather clear, but I won't insist.
> How would we tell? The productivity of the technology industry as a whole has certainly risen enormously. My general impression is that coding is the bottleneck a lot less often - even for a technology company - than it was five or ten years ago.
Is it? I've been a professional developer for 20 years and while I agree that productivity has gone up considerably (maybe 2-3x) it can be attributed nearly entirely to automated tests and GCs.
Good -- and simple[1] -- abstractions require lots of dynamic dispatch, that can be optimized away by a JIT. The problem is far simpler (and may be solved partially, AOT, if you don't have dynamic linking and especially dynamic code loading, as is the case on Android).
> and array-bounds checking (um... is that last one a "linguistic" feature?)
I would definitely classify that as extra-linguistic.
> But I meant by my statement, that these folks think intrinsic value is the only "real" value, that they dispute extrinsic value entirely! i.e. that ideas are eternal, valuable absolutely and despite context; and contingent fluctuations in supply and demand, progress of technology and install base etc are 100% meaningless.
I understand and completely agree.
[1]: You can do away with a lot of dynamic dispatch at the cost of a larger number (and therefore less simple) abstractions, as in the case of Rust.
So they don't need the JIT per se, but for linguistic abstractions... to be performant, which is non-linguistic. That's splitting hairs though. So, James' customers needed those abstractions, and _he_ said they needed a JIT.
Incidentally, I've been doing dynamic code loading on Android 5.0, with its AOT. So it works. For my use, it's hard to tell if its startup is slower, though I'd expect it to be.
I hadn't heard that about Rust.
How does that work? Or is their AOT really a JIT that works all at once, rather than collecting a profile first?
> I hadn't heard that about Rust.
Basically, in Rust (as in C++) you can pick either static dispatch abstractions, which are "zero cost", and dynamic dispatch abstractions, that are more costly. On the JVM you get dynamic dispatch as the abstraction, and the JIT figures out whether static dispatch can suffice per callsite, and compiles the dynamic abstraction to static-dispatch machine code.
> Is it? I've been a professional developer for 20 years and while I agree that productivity has gone up considerably (maybe 2-3x) it can be attributed nearly entirely to automated tests and GCs.
I think productivity is noticeably higher than even five years ago, when we already had GC and widespread testing.
Thanks for the info on rust.