1. How cumbersome a language is to use (as a beginner, as a confident developer, etc).
- C++ is rather easy to start, but takes ages to master and surprises even powerful users daily.
- Rust is hard to start, it states complexity of systems upfront in a tightly packed knot that should be handled all at once, but once you're past that, it's rather consistent.
- Haskell is very hard to start with, it is basically unlearning every imperative habit, but again, after that it's a powerful and mostly consistent tool (not without its warts, but drastically less than C++). There is some tolerance of complexity in the ecosystem, but it is clearly encapsulated in libraries and justified by papers and research interests.
2. How complex is the abstract core of a language.
- Haskell has had an amazingly simple, elegant and consistent core for decades; on the other hand, modern Haskell has accumulated a lot of research-y stuff (which is still optional to use), which may be nice/cumbersome depending on the situation. Run-time behavior feels woefully underspecified though, and can be flaky and hard to reason about.
- the mental model of Rust is bigger and more complex than in Haskell (traits, generics, lifetimes/onwership, the underlying C-like memory model), but it's definitely practical (if somewhat spartan) and consistent.
- C++ does not have a coherent vision at all: it is a pile of organically grown features with interesting (and sometimes useful) interactions. This pile is outright impossible to reason about formally.
The only definition in which "C++ is not more complex" is the definition of being easy to use for a beginner in the language.
Having used c++ for many years, this does not come across as a ringing endorsement for looking into Haskell or Rust.
I'm quite happy with my current gig using Go. Looking back, the culture of complexity surrounding c++ is obvious, but talking with my peers who have only ever done c++ - it's like they have Stockholm Syndrome.
Any language (or tool for that matter) that you have to invest heavily in, and use for a while will produce a symptoms of "Stockholm Syndrome". Moreover, once you are hard pushed to switch from it to something else, withdrawal symptoms are quite pronounced too.
Go has its own share of idiosyncrasies, and it drives me nuts sometimes even more than C++ did, but these bursts of mental grind are less common and much shorter in comparison :). The arcane complexity of C++ (and tooling around it) is something that I don't miss at all.
I sometimes like to dabble in C++, late at night, while sipping some whisky. For short periods of time.
Last night, I decided to "practice" writing iterators. Specifically, I wanted to write a class that i could use in a new-style C++ range loop that would give me all files in a directory. Useless but fun practice, I thought.
I had Bjarne's latest book by my side, and the final draft of the C++17 spec in open in a PDF, and it took me a good 2-3 hours of trying before I "got" it.
I'm still not sure I'm doing it correctly, btw. It does compile without warnings, and it works, but I can tweak the iterator function signatures in seemingly incompatible ways and it still doesn't complain and still works, even when I swear it shouldn't. "Ok, surely by doing this I'll break it!" - nope, still works.
I don't love everything about Go, and once in a while I'll wish for more expressiveness, but I was never, ever, as 10% confused with it as I am with whenever I attempt to do something seemingly trivial in C++.
C++ is not more complex than its competitors like <insert two languages that have little in common yet C++ can be considered competition to both of them because it is such a complex beast>
What they have in common is a complex compile-time static typing system.
The source of complexity isn't a mythical "culture of complexity", the complexity is there because it's inevitable if you want to implement powerful compile-time type reasoning. (And you definitely want compile-time reasoning because it's the only way to guarantee performance and correctness of programs.)
The case of Haskell and Rust proves that the issue isn't cultural, it's inherent to the problem domain.
What exactly do you mean by "a complex compile-time static typing system"? I'm not familiar with Rust, but C++'s and Haskell's typing systems don't look very similar, or even of similar complexity.
I do agree there's an inherent complexity in the problem domain. It's just that some languages are more helpful than others in dealing with this complexity :)
PS: my own bias: Haskell's seems both easier (in general) and more helpful than C++'s.
> C++'s and Haskell's typing systems don't look very similar, or even of similar complexity.
yet they are. The difference between the Haskell type system and the C++ type system is that generic constraints on types are explicitely specified with typeclasses in Haskell, while they are implicitely specified with templates in C++ (though this changes in C++20 with concepts).
To make a "conceptual leap" beyond the C++ and Haskell type systems, you have to use a language with dependent types such as Idris or Coq (and actually, dependent types can be simulated in C++ ! http://pfultz2.com/blog/2015/01/24/dependent-typing/ but like all simulations, it will be slower than if it was implemented directly by the compiler).