This is a good post! A few comments:<p>> Function Overloads<p>Strictly speaking, Rust doesn't support overloaded functions. Function overloading is when you define the same function but with different arguments, and the language selects the correct one based on the argument type. In this case, it's two different implementations of a trait for two different types. That said, it's close enough that this isn't really an issue, more of just a technical note, since this is a series trying to get into details.<p>> I can't find an explanation in the Rust documentation but I expect the reason is that someone could implement another trait that provides .into_iter() on whatever the x is in for y in x, thus resulting in a compiler error because there would be two candidate implementations.<p>Yep, I'm not sure that there is an official explanation anywhere else, but this is exactly what I would assume as well. This ensures that the correct implementation is called. This is also one of the reasons why adding a trait implementation isn't considered a breaking change, even if it could create a compiler error, because you can always expand it yourself to explicitly select the correct choice. Of course, these situations are usually treated more carefully then they have to be, because breakage isn't fun, even if it's technically allowed.<p>> But wait, you say, I'm doing exactly this in the first program, and indeed you are.<p>It's not the same, as the next paragraphs explain.<p>> We are able to examine the function and realize it's safe, but because the compiler wants to use local reasoning, it's not able to do so.<p>This is a super important point!
This is pretty good.<p>A useful way to think about this:<p>- All data in Rust has exactly one owner.<p>- If you need some kind of multiple ownership, you have to make the owner be a reference-counted cell, such as Rc or Arc.<p>- All data can be accessed by one reader/writer, or N readers, but not both at the same time.<p>- There is both compile time and run time machinery to strictly enforce this.<p>Once you get that, you can see what the borrow checker is trying to do for you.
The first code snippet, which is as simple as it gets, perfectly illustrates why Rust is extremely annoying to work with. I understand why you need the into_iter bit and why the borrow checker complains about it, but the fact that even the simplest "for x in y" loop already makes you wrestle the compiler is just poor ergonomics.
We'd expect in the 21st century we have programming languages that have impeccable GC for automatic memory management rather than forcing programmer to wrestling and fighting for manually managing the memory.<p>Auto industry kind of solved this automation mechanism for example with the new high performance Toyota GR Corolla has a new automatic gear transmission that's proven as fast if not faster than the manual version [1]. The same goes to F1, the epitome of car racing performance.<p>[1] 2025 Toyota GR Corolla's New Automatic Gearbox Democratizes Fun:<p><a href="https://www.caranddriver.com/reviews/a62672128/2025-toyota-gr-corolla-automatic-drive/" rel="nofollow">https://www.caranddriver.com/reviews/a62672128/2025-toyota-g...</a>
I'm starting to think Zig's strategy to memory management is generally friendlier to a developer. If a function needs to allocate memory, it must take an allocator as a parameter. If it needs scratch space to perform computation, it can use that allocator to create an arena for itself, then free it up before it returns (defer). If it returns a pointer, the caller should assume the object was allocated using that allocator, and becomes the owner. It may still be unclear what happens to a pointer if it's passed as a parameter to another function, but I'd normally consider that a borrow.<p>It's a lot of assumptions, and if you trip, Rust will yell at you much more often than Zig; and it will likely be right to do so. But in all seriousness, I'm tired of the yelling, and find Zig much more pleasant.
A 20 page document on how to use basic variables, function calls and methods. Except for the threading paragraph, which is hard in any language, this is all complexity and refactoring pain that Rust hoists onto every programmer every day, for relatively modest benefits, somewhat improved performance and memory usage vs the garbage collected/ref-counted version of the same code.<p>Essentially, you wouldn't and shouldn't make that tradeoff for anything other than system programming.
I really like the text. Giving more light to the memory management of rust will help me understand more of the language. I still think some concepts of rust are over verbose but I slowly understand the hype around rust. I myself use C or C++ but I will „borrow“ some of the rust ideas to make my code even more robust
been banging my head against this same stuff trying to learn rust - honestly memory rules make me miss how easy c feels sometimes, but i'm sticking with it cuz i want fewer bugs