Ahhh the joy of the borrow checker :
Me: Let's code this little vector computations
BorrowChecker: "Not like that"
Me: "What do you mean I have borrowed a mutable ? Let's try something else purely out of random"
BC: "No"
Me: "Let's rename things to cheat"
BC: "No"
Me: "Ah yeah, it's because I try to use two indices in the same vector"
BC: "No"
Me: "G*mn at random, let's shuffle things"
BC: "No"
ME: Ok, let's do it in python
(but believe me, once, you understand it and it becomes a really good friend, it just takes months :-) )
Coming from C++, it didn't take months. I got a couple lifetime errors at the start, but I understood the reason behind them all[1]. Now I don't get the errors[2]. In C++ you need to think about the lifetimes anyway or your code will break at runtime, so then coming to Rust it's not that much of a problem IMO.
[1]: Except the errors about partial (non-aliasing) borrows of struct fields. That was annoying, although circumventable with some boilerplate. Luckily, it's solved now in the compiler.
[2]: Although it may be to a large degree thanks to using arenas for allocation, which simplify lifetimes a lot by grouping them into large buckets instead of tracking each little object separately with its own little lifetime.
>> it may be to a large degree thanks to using arenas for allocation
If you're going to do that, would you not be better saving all that time and code bloat (it's code you wrote that doesn't contribute to solving your problem) by just using a garbage collector from the outset?
This propensity to fall back to arenas and the other puzzling behaviour i observe is liberal use of "#[derive(Copy, Clone)]" - these seem counter productive. Why are people wasting time only to reinvent solved problems?
Or to frame it more charitably, rust is allegedly a super-power for developers. Why are rust devs not pushing the boundaries of what it means to be a developer? We do we not see very large code bases on github maintained by a small number of devs? Allegedly the combination of static typing + borrow checker makes code maintainability a breeze. So where's the evidence?
I suspect a garbage collector would be pretty nice. However, I can't just list the features I want and get a language (unless I make it myself, which would take a lot of time). Currently, my imaginary perfect language would actually have a garbage collector, would be pretty similar to Standard ML, but would be more focused on arrays than lists, and would have value types --- in Standard ML I can't have a value array of records (structs in Rust/C++ parlance) --- they will be behind a pointer. And if I were to stick to the standard or make sure that my code compiles with other compilers than MLTon, then I can't even have a value array of 64-bit words, although I can have a value array of 63-bit words. This one bit may seem insignificant, but for certain algorithms it's a big complication. Powers of 2 simplify a lot of algorithms (and are "faster" to be a bit loose with the language). There are other features I'd like, but already this short list makes for a currently-non-existent language. OCaml and Haskell have similar problems to Standard ML.
At the same time Rust has great support for arrays, is expression-oriented, has sum types. Value types are the default. It generally ticks a lot of boxes I care about. I can't just go and say "now give me all that but with a GC" and have it appear before me.
Also, arenas I use are linked to logical portions of my programs. They are not contrivances that I had to think long and hard about. They don't waste my time really. I've spent 0 time thinking about how they should be organized.
Now the part where a GC would be helpful is a bit of a more liberal use of closures, and eliminating code noise coming from lifetime annotations such as "for<'a>". But I can live with the current state of affairs, if I get all the other benefits.
> If you're going to do that, would you not be better saving all that time and code bloat (it's code you wrote that doesn't contribute to solving your problem) by just using a garbage collector from the outset?
If anything, Rust is an asset for large teams of devs. Even though you may sometimes argue that a handful of C/C++ devs can keep their whole project in their heads and not make mistakes (although I think that's a stretch), the moment you get a large C/C++ team, weird hard-to-debug bugs coming from memory- and thread-safety issues start to creep in. There are other high-level languages, but Rust is the one with a combination of performance competitive with C++ and large ecosystem of libraries you can use. Examples of Rust projects with a large number of contributors facilitated by the language taking the fear of intractable bugs away:
- <https://github.com/BurntSushi/ripgrep>
- <https://github.com/clap-rs/clap>
- <https://github.com/rayon-rs/rayon>