Minor point: you can have Vectors in structs. Vector is a fixed-size type on the stack so it works fine. And other types in structs too. EDIT: sorry, I see you got to that before I'd finished this post :)
Rust is a language where you have to kind of take a step back before working with it to read about the design tradeoffs and why they were made. Certain things you're used to doing with other languages just won't work (e.g. doubly linked lists), and trying to coerce the language into being something it's not leads to you going on one of those frustrating circular rabbit hole journeys you described so nicely above, usually ending up with laptop defenestration.
I'm a week into Rust. I find like you the compiler quite helpful, the docs comprehensive but a bit impenetrable, and the ownership & lifetime system logical on its own terms but very, very unnatural to learn. I don't actually know if its worth it yet.
I am really, really enjoying the O'Reilly Rust book ("Programming Rust"). Maybe sign up for a 10 day Safari trial (free, no card) and give the first few chapters a read. It may help reset you.
> lifetime system logical on its own terms but very, very unnatural to learn
That is a succinct explanation of it, yes! Like I can read the documentation and nod along, and the rules seem simple. Actually then remapping your brain and how you want to achieve things seems incredibly challenging
Actually then remapping your brain and how you want to achieve things seems incredibly challenging
The thing that I have come to appreciate more strongly is that you actually have to think about the same ownership rules in other languages to write bug-free code. Consider e.g. the following Go code:
Whether a subslice is still referring to the same array as the slice that it was derived from depends on whether there were any appends that required allocation of a larger backing array. Whether/when this happens is an implementation detail.
Rust prevents this ambiguity by not letting you borrow a `Vec` simultaneously as immutable and mutable (or multiple times mutably). Since the `push` method takes `&mut self`, you cannot have any mutable/immutable slices of the same data.
Another example. If you take a slice of a large array and only use that slice from there on, the slice will (obviously) prevent garbage collection of the backing array [1]. Again, Rust's ownership system prevents such memory leaks, since a slice reference cannot outlive its (owned) `Vec`.
I would argue that the cognitive load in other languages is actually higher if you want to write correct code (except perhaps in languages with immutable data structures, such as Haskell), since you have now compiler helping you out. It's just that other languages allow us to cheat when it comes to ownership. For worse or better.
Well, that's down to practice. And on that subject...
One thing I like to do with a new language is to re-implement a self-contained but non-trivial program that I've built before. I have a few but my favorite is a genetic algorithm which breeds rule sets for a cellular automaton to get the CA to solve some simple computation problems. It's not at all complex, a few hundred lines when done in Python, but it's more than a tiny example. I like it for learning new languages as it touches on various data structures, it's inherently parallelizable, it's not especially bound to any particular programming paradigm, it lends itself to exploring various useful concepts and constructs (function pointers, closures, recursion, etc.), and it is fun and interesting to work on.
So maybe you have something similar, something where you really understand the problem and the solution, freeing your brain to focus entirely on seeing how it would map to Rust.
I have been looking for such a problem to use as you to, to kick the wheels of languages. I would like to also include some basic linear algebra and/or signal processing to test numeric stuff. But do you have an example upbon github or similar? I've got a couple decades of c++ experience and I'd like to move more into rust for my home projects but I haven't had one that really tested me with data structures and threads.
I'm still in the early stages with this one in Rust. I spent a lot of time this weekend on it and I'm finding no exaggeration in those stories of fighting the borrow checker! It's been a pig, honestly. I am OK with the point of it all, if anything it's made me more aware of limitations of not taking this strict approach in other languages. I can see all sorts of possible bugs that can't happen in Rust. Doesn't make writing it any easier.
I'm starting to think that Rust is really just a clever set of constraints that forces good behavior on the programmer.
Happy to throw the Python stuff over the wall at you although it isn't especially pretty (it was my 'learn Python' project). I'll put it up on Github this week & ping you back here.
Rust is a language where you have to kind of take a step back before working with it to read about the design tradeoffs and why they were made. Certain things you're used to doing with other languages just won't work (e.g. doubly linked lists), and trying to coerce the language into being something it's not leads to you going on one of those frustrating circular rabbit hole journeys you described so nicely above, usually ending up with laptop defenestration.
I'm a week into Rust. I find like you the compiler quite helpful, the docs comprehensive but a bit impenetrable, and the ownership & lifetime system logical on its own terms but very, very unnatural to learn. I don't actually know if its worth it yet.
I am really, really enjoying the O'Reilly Rust book ("Programming Rust"). Maybe sign up for a 10 day Safari trial (free, no card) and give the first few chapters a read. It may help reset you.