I find myself in agreement with many of the things that you say here. But you know, poor old Beelzebub needs a lawyer. So here is my attempt at representing an alternate point of view.
If your only objectives when building a programming languages are usability for experienced users and advanced static type system capabilities, then you get a programming language like Haskell, and I think it is important to realize that while admirable in many ways, this role model is not without its issues.
Haskell is a successful programming language. Its type system lets you do crazy things that are checked at compile time, and it manages to take keyword noise and redundance to a ridiculously low level. But any time I tried to learn it personally, I got stuck in front of the wall of sigils, impenetrable user jargon, and underlying assumption of much documentation that I knew category theory or cared enough about it to face the complexity wall of learning it before I can be comfortable with this programming language. So if Rust went in that direction, it would be without people like me or a similar background.
As a language designer, it takes conscious effort, and a careful attention to detail and newcomer experience, in order to avoid falling down this path. When you’re used to it enough, and know how to avoid the deadly traps so well that you don’t even think about them anymore, even a mess like C++ can seem reasonable. Worse yet, many beginner complaints will never be expressed publicly. It takes a fight against one’s ego to dare ridicule yourself by asking a question on something “which must be obvious” on the forums, so some people will just silently get used to the roadblock and either learn to get around it or give up, just like inexperienced Windows users will over time get extremely efficient at dismissing recurrent incomprehensible error messages on startup.
This is why, in my opinion, it is good for programming language designers to also think about the papercuts.
Concerning this, your other point is that now is not the right time to think about them. That we have more important things to take care of first. That we should be working on the plumbing before we can paint the top of the house.
I would agree with that if Rust was still publicly presented as an experimental language with a big “DO NOT TRESPASS UNLESS YOU ARE READY FOR THE WORST” sign at the entrance. But it’s not. Rightly or wrongly, some of us have decided that the language was already in a good enough shape for some use cases, and that the time was right to market it as a stable platform that one can start building stuff on. Now that we do this, we get plenty of curious beginners. And as soon as we have beginners, we need to care about them, which you personally contribute admirably to every day.
One of Rust’s crazy gambles is to make advanced type system features easy to get started with as a beginner. It manages to hide the complexity incredibly well, and to let one use the language without fully understanding what’s going on at first, then gradually acquire a more advanced understanding over time. I think that’s one very precious property to keep as the language evolves. We should not abuse this because correcting an incorrect understanding during the learning process is always painful, but it’s good that we can afford to introduce some pretty crazy stuff down in the type system without scaring away most of the beginners like Haskell does.
Because for every user that gets stuck in the learning process and goes away, we get public complaints about how Rust is impossible to learn, and unworthy of attention. We get companies that run internal evaluation of the language out of the curiosity, and get away from that with a feeling of “not worth learning it”. Rust is toying with the boundary of this all the time, and it’s important to realize how fragile our position is, how big the gamble was.
In that sense, now is the right time to care about beginners. As a young language which just went past stabilization, Rust is now at a critical stage of its evolution where it needs to convince the programming community that it is worth learning and building stuff with. From this point of view, beginner experience matters in many ways now a lot more that it will in the future, once things are more established, we have many production users, and we are at a lesser risk of short-term extinction.
From this point of view, I can see the point of, say, match ergonomics. Match expressions are one of the first things that one learns as a Rust beginner. But by forcing you to explicitly destructure everything, they break a bit this “illusion of simplicity” that things such as method syntax or deref coercions managed to build. From this, I see two paths : either we consider pattern matching as an advanced topic, and we teach it much later in the language learning process, or we make it more approachable to newcomers by allowing them to stick with some illusions of understanding for a little bit longer. So far, we took the later option.
I also disagree with you that NLL is that different. One of the ideas behind lexical lifetimes was that the lifetime mechanism should be easy to understand correctly, by reusing the intuitive understanding which one has built from Drop. NLL builds on the observation that making this feature easy to understand correctly was not worth the trade-off, caused too much pain, and that it was better to go towards a mechanism where it is easier to get away with a wrong intuition because the language gets closer to “do what I mean”.
To conclude, feature prioritization is a difficult problem, but I think that beginner-oriented features also have their place at this stage of Rust’s evolution. I hope I have done a decent job at defending this idea, in spite of having little time available to write and correct this post (which is likely full of typos, rambling and redundance)…
…even though personally, the things that I’m most interested in now that I’ve went past that learning stage are const generics and SIMD