I'm particularly interested in why several languages show up on both lists, namely SQL, Scala, Haskell, Shell, and HTML if you count it.
One possible explanation (that supports the author's main thesis) would be that three out of five of these are unlikely to be the main language for a project, but rather a supporting language. In other words, SQL and shell are just as likely to show up in a green-field project as in a brown-field project, because we still use SQL to communicate with database same as 20 years ago, and we still use shell scripts to tie it all together.
No idea how one would test this hypothesis, however. And I still don't have an explanation for why Scala and Haskell are both loved and hated.
Scala and Haskell are both "astronaut" languages. They really encourage highly complex abstractions. They're potentially very powerful, but it's easy to get lost in the clouds.
Some people love it, because it potentially gives you an enormous amount of leverage to solve difficult problems with careful but short solutions. I forget where I heard this joke, but you give a Java programmer some specs and he'll spend 4 hours writing code, whereas the Haskell programmer will spend 3 hours and 55 minutes meditating, then write a 10 line solution.
The counterpoint is all that abstraction is often just needless busy work, that more often serves to feed the programmer's ego rather than accomplish real work. It's also not pleasant trying to figure out compiler errors that you need a PhD in abstract algebraic topology to understand.
> Some people love it, because it potentially gives you an enormous amount of leverage to solve difficult problems with careful but short solutions. I forget where I heard this joke, but you give a Java programmer some specs and he'll spend 4 hours writing code, whereas the Haskell programmer will spend 3 hours and 55 minutes meditating, then write a 10 line solution.
I prefer the "meditative" approach, because it will more often produce something readable. It looks unproductive, because there is a small number of lines produced in a given amount of time, but that's actually good. With the approach where the programmer just sits down and bangs away at the keyboard straight away, producing lines of code at uniform velocity, you end up with loads of code doing nothing, "dowork", calling "doworkimpl", stack traces 50 stack frames long where no stack frame seems to be doing any useful work. The "meditative" approach in extreme cases can produce indecipherable code with y combinators and whatnot, if your coworker is a real monk, but generally brevity seems to be a nice benchmark. All those great Haskell abstractions don't actually produce short code, it's the basic Haskell that does it. It just takes a while to arrive at such a solution, be it C or Haskell. And it's a win long-term, when you need to get back to this code to debug it. And you are going to need to get back to debug it.
See e.g. The Evolution of a Haskell Programmer[1]. It's not the great abstractions that produce the shortest code. But it is the shortest code that is the clearest.
> Scala and Haskell are both "astronaut" languages. They really encourage highly complex abstractions.
Haskell encourages very simple but highly abstract abstractions. Scala, I would agree, tends high complexity as well high abstraction level.
Both can be barriers to understanding if one is not familiar with the particular abstraction, but they are different issues (high abstraction level tends to be something you go from not getting intuitively to getting intuitively in a phase transition, while high conplexity tends to be more gradual and has a greater irreducible cognitive load.)
> Scala and Haskell are both "astronaut" languages. They really encourage highly complex abstractions
They encourage highly simple abstractions. You can put functions like `fromString` and `map` onto interfaces. No need to go via builders/generators/collections.
Dijkstra said it best: "The purpose of abstraction is not to be vague, but to create a new semantic level in which one can be absolutely precise."
> It's also not pleasant trying to figure out compiler errors that you need a PhD in abstract algebraic topology to understand.
I'd much rather deal with that and become better in my profession than being woken up at night because something is on fire at runtime and I have to jump in and understand it, fix it and clean up after it.
> I forget where I heard this joke, but you give a Java programmer some specs and he'll spend 4 hours writing code, whereas the Haskell programmer will spend 3 hours and 55 minutes meditating, then write a 10 line solution.
Given the choice of reviewing and maintaining one versus the other, I’ll take unwashed Java code any day. I’m not a fan of enlightened, esoteric solutions.
Reviewing 10 lines is likely easier than reviewing 500 lines that do the same thing.
Also something that is beautiful is not necessarily esoteric (though esoteric isn't really meaningful anyways. Chinese sounds esoteric to me just like English sounds esoteric to others).
But it really comes down to experience, not the qualities of the language. A professional in both Java and Haskell would most definitely prefer a few line Haskell solution vs a massive Java solution. Just like they would prefer a few line Java solution over a massive Java solution.
> an explanation for why Scala and Haskell are both loved and hated
I would posit it's unlikely that the same people both love and hate them. My guess would be we're seeing the OO-FP divide in action. If F# or Elm were more popular, they might be on both lists, too.
In fact, if you interpret it liberally, JavaScript might be considered FP by some takers of the poll, given browner JS codebases (pre-await) would need continuation-style approaches. Obviously, JS has other [reputation] problems, too.
I cant speak for Haskell but imho earlier scala codebases suffered from either too much javaism or too much haskellism. The language is so flexible, you can write code either way. People brought too much baggage. Javaists brought Spring Guice and tones of other sht that simply does not belong in Scala, Haskellers did their darn best to write Scala code exactly like they would write it in Haskell with very little consideration for Scala or JVM. The results in some code bases aint pretty. You basically need to know Haskell, Java, and Scala to read the code where people have went overboard.
Having said all that, Scala is still my favorite language on the JVM, and Scala3 really stands on its own when compared to Scala2 more hybrid approach
What is the native Scala style? I have heard of things like "cake pattern", initially touted as the bees knees then falling out of favor after there was some experience to draw from their usage.
It's obvious, but no one seems to notice it: These are not two lists. The list of dreaded programming languages is the list of loved languages reversed. Since the list has only 25 items, 5 languages belong to the top 15 in both directions.
Haskell is an oddball in that it’s an older language, created in the 90s, IIRC a year before Java, with concepts so cutting edge that it was utterly useless. Initially they hadn’t even worked out how to do IO. Probably it’s only been useable in industry for maybe 10 years. So Haskell is relatively old, but you’re unlikely to encounter a lot of old projects written in Haskell. Also, there’s a lot of hype about how difficult it is, I believe this has a lot to do with how different it is from popular languages people already know. In my experience, once learned it can be hard to go back to other development styles.
> Initially they hadn’t even worked out how to do IO.
I tried to find some date by which they'd figured it out, the best I can do is 1992[1].
To put it another way, Haskell's had a great story around IO for 29 years, or longer than Java's been around.
All the modern future/io/concurrency frameworks have followed suit. We construct objects representing computations and we flatMap them together, which is all the IO monad is. Although for some reason the syntax from last millennium hasn't made it into the modern languages:
> Haskell's had a great story around IO for 29 years, or longer than Java's been around.
I like that a lot. I did not realize that problem was solved so early on.
The things I was thinking of were more like good application frameworks, database libraries, etc. all the stuff you need to build commercial products and that you might have trouble justifying developing on an investor’s/shareholders’ dime.
The popular syntax for this in newer imperative languages seems to be async/await, although I think I only like Swift's implementation. (unfair statement since I haven't used the rest much)
The cool thing about the syntax in Haskell is it’s not tied specifically to async, you can use it for synchronous IO, business logic, parsers, etc. It makes for small context switches when working on different parts of an application.
Lazy IO is so irresistible that it was added to Haskell
despite the reservations of its inventors and the failure
to develop good techniques for reasoning about its correctness
[7, Sec 10.5]. However benign, reading is an observable
side-effect, whose occurrence may have to be correlated with
other side effects. Such correlations are crucial when
performing IO over communication pipes, which is typical of
web servers.3 As Launchbury and Peyton Jones feared, Lazy IO
indeed "gives rise to a very subtle class of programming errors".
We have seen deadlocks; mishandling of IO errors; running out of
file descriptors and similar scarce resources; unpredictable,
volatile and sometimes unbearably excessive use of memory. We
illustrate the splendors and miseries of Lazy IO in §2.
This is a very famous Haskell programer's opinion on the default IO in Haskell, and he quotes that one of the main creators of the language himself anticipated such problems [2]. Why downvote a comment in 2021 challenging the claim that "Haskell's had a great story around IO for 29 years"?
Iteratees (nowadays pipes, conduit etc.) are based on functionality that was already there in 1992. They didn't add anything to Haskell. They're just libraries. Lazy IO has indeed always been bad but it wasn't the only part of Haskell's IO story.
What were the other options available in Haskell in 1992, besides Lazy IO, which made for a great IO story then? Please point me to code or papers from then because I am genuinely interested to learn.
Reading and writing between handles and buffers, just like any other language. If you object specifically to the adjective "great" then, well, I don't think that was the operative point of the original comment.
"Lazy IO" is things like `readFile :: FileName -> IO String`, where that String you get back secretly hides a thunk that will read more from the file when you evaluate it (even in pure code).
The operations provided by `Data.ByteString` do not work like this; the ByteString you get back represents a buffer, and it has already been processed by the time the RHS of >>= starts executing.
The operations provided by `Data.ByteString.Lazy`, on the other hand, do work like that; the ByteString you get back is a linked sequence of buffers, and some of those links might be thunks to go get the next bits of the ByteString for you.
This is why a Data.ByteString.ByteString and a Data.ByteString.Lazy.ByteString are different types, and you can't just pass one where the other is expected (unless you've abstracted over it) - they're actually shaped differently.
For Scala and Haskell, it could just be pragmatic developers vs purist developers (to grossly generalize).
There are people out there who want the absolute best language for a project, even if they don't already know it.
Then there are those who would be annoyed at having to learn a new language and all its quirks to do something that Java could have done, even if it cost more in servers or requires more lines of code.
Well, three things on that list are languages that are basically DSLs (Shell to a degree, SQL) or Markup Languages (HTML). Comparing any of those to e.g. C++, Go, Ruby or Python is like comparing apples to oranges and I don't see, how that is a useful distinction.
Scala and Haskell are distinctly non-C-like. Both are functional languages with types. Maybe that is a factor.
Actually, in a new project that wouldn't be "low-level" work on e.g. operating systems, drivers or high-throughput networking software I would strongly suggest using Clojure/ ClojureScript. The net productivity, onboarding speed and efficiency are great. Both are quite performant as well and integrate into the Java/JavaScript world with ease, so there are libraries and tools present. Using babashka or the Node.JS target for ClojureScript could be great for scripting as well, although Python or Hy (Clojure on top of Python basically) are strong contenders because of libraries.
Scala is a kitchen sink language. You can write it like FP, OO, or anything inbetween. So you're bound to get codebases that aren't written in the developers preferred style.
On top of this, lots of companies started using Scala because Java hit a long period of stagnation. So these companies have a mix of Java/Scala and a primarily Java developer - that likely doesn't like kitchen sink languages - may be required to maintain a Scala program from time to time.
It's also the only viable language with a decently sized community that allows you to write mostly FP or even fully FP code on the JVM. And one strength is that you can go from OOP via OOP+FP to fully FP if you want.
Yes, that can also cause a mess, but for learning it is one of the best languages out there imho.
Can't really speak to Scala and Haskell, but shell, HTML and SQL all are generally love/hate languages. All three are pretty simple to be productive with, and all three take a lot of time and knowledge to master (I'm including CSS in with HTML). All three are powerful, yet have pretty big limitations, too.
4 of those 5 (all but Shell) are very declarative languages. They tend to be very concise and powerful, but are quite different from the more imperative languages people are used to.
Could be that once you really grasp them, you love them, but they’re harder to grasp because they’re so different?
One possible explanation (that supports the author's main thesis) would be that three out of five of these are unlikely to be the main language for a project, but rather a supporting language. In other words, SQL and shell are just as likely to show up in a green-field project as in a brown-field project, because we still use SQL to communicate with database same as 20 years ago, and we still use shell scripts to tie it all together.
No idea how one would test this hypothesis, however. And I still don't have an explanation for why Scala and Haskell are both loved and hated.