"The last question I will inspect here is that, if Ownership is difficult to learn and use for so many
reasons, why do developers choose to use Rust anyway?"
Ownership is not that hard. Borrowing is a bit harder but not that much more so.
I use Rust because of the ownership and borrowing systems, not despite them. They help me design systems and write code which has very few bugs once it compiles. (The last code I had with bugs in it I wrote maybe 2 months ago.)
I hope some useful pedagogical work comes out of the whole project, but I'm really doubtful of the premise.
Anecdotal, but I recently had the opportunity to write some relatively greenfield code in each of Rust and C++. Nothing too massive, a few thousand lines. But fairly intricate code with a need for high performance. I consider myself to be fairly advanced in both languages (but not can-write-the-spec level advanced).
I was shocked at how many memory corruption / uninitialized data errors I was hitting in C++, for what (I thought) was fairly nice, modern-ish code. This is for code that builds cleanly with -Wall -Werror, with exclusive use of .at() instead of unchecked vector/map access, etc. There are just far too many ways to end up with uninitialized data, and the ecosystem (think serialization libraries) don't really help you there.
I didn't realize how much of a cognitive burden Rust was relieving me of. Sure, the borrow checker is a pain. But I have confidence that when my code builds, it will be entirely free of certain classes of bugs. And other classes of bugs are well-managed by Rust's compiler warnings and Clippy lints.
There seems to be a sort of sleight of hand in programming communities where when Rust is hard, we blame it on the language, but when C++ is hard, we blame it on the programmer. I didn't see the article do a good job of teasing this out.
> There seems to be a sort of sleight of hand in programming communities where...
I don't think there's anything sinister here, just the classic difference between old and new. Old things are familiar, and their downsides are facts of life. New things are threatening, and their downsides get a lot of scrutiny. I'm not even complaining; it's a pretty reasonable heuristic most of the time.
I agree it's not sinister, but I think it goes deeper than this.
Strong (static) type systems fundamentally make you do more work up front. They force you to be more explicit. They restrict what you can do. They're in your face, because you can't get your program to compile without them. No one gets through any significant amount of Rust programming without knowing that the borrow checker is there. It's so fundamental that it's just part of the experience.
C++ arguably has just as many rules for writing "correct" programs, but they're not enforced by a compiler. So much stuff happens by convention. If you follow the convention, great, your code is safe. If you mess up, no one catches you. Because it's your responsibility, it's easy to attribute this failure to your programming skill rather than to the language that made that mistake possible in the first place.
I'm not saying stronger type systems are always better, but I do think there is a fundamental human tendency to attribute the up-front as hard and the latent as easy, even if the up-front work ultimately helps you avoid the latent work down the line.
> Ownership is not that hard. Borrowing is a bit harder but not that much more so.
I guess this is a bit like Typescript then. Especially when it comes to generics, sometimes I need to sit down and think carefully about what datatype exactly is it that this method requires compared to what I have and how do I express it in a generic way.
Sometimes it ends up taking some time but the result is invariably that the code ends up easier to read, understand and modify.
It would be interesting to see alternate languages with the ownership model but without the burden of the alien syntax, complex type system, and added complexity of macros. All of which make learning rust a burden. I constantly go like "Wtf does this piece of code even do?" when looking at rust code. And it doesn't help that the libraries and documentation is riddled with type system jargon. I'm sure it's all necessary. But it is not simple.
It might get easier without all that but is that even possible? The concept of borrowing at it's core isn't that hard to grasp: you taking ownership of something means that somebody else doesn't have it until you release it back to them. Easy. But we seem to have a sample of 1 when it comes to rust style ownership. At least, I'm not aware of other languages doing this. It seems to have lots of advantages. Which raises the question why this obviously good idea is not being replicated by others.
It's been a while since I started learning Rust, and have the advantage of learning new constructs as they are being implemented before they even hit stable, so I find it hard to put myself in your shoes. Could you give some examples of alien syntax whose functionality you couldn't extrapolate from other constructs? rust-analyzer does provide on-hover documentation for keywords and (some) sigils, but it isn't as discoverable as it could be and I can believe that there are documentation "bugs" of missing explanations for specific use-cases, even in The Book!
The wisdom for programming language adoption is that you need to be able to do nothing in 3 minutes (exitCode 0 = success), do anything in 10 minutes (pick a softball problem for your tutorials that avoids the difficult parts of your language), and do something in an hour.
With that in mind, you don't have to remove the model, you just need defaults that can get you past that 1 hour mark, and people will stick around long enough to put in the time and effort to figuring it out.
Most simple problems don't need shared state in order to work, so a language that makes assumptions, such as no sharing by default, could kick that can down the road for a bit. A lot of recursive and some iterative examples only ever accumulate state on the stack. You don't need shared state until you interact with an external system, such as another computer or a human.
Is there a simpler model out there, somewhere between Rust and Haskell, where -nobody- owns the objects and all arguments are pass-by-value unless otherwise stated or inferred?
Pure functions should be able to share objects. The problem I suspect is working out the calculus of transitioning from stateful into stateless code, but the plus side is that you end up with a programming language that enforces functional core, imperative shell.
Ownership is not that hard. Borrowing is a bit harder but not that much more so.
I use Rust because of the ownership and borrowing systems, not despite them. They help me design systems and write code which has very few bugs once it compiles. (The last code I had with bugs in it I wrote maybe 2 months ago.)
I hope some useful pedagogical work comes out of the whole project, but I'm really doubtful of the premise.