Earlier quoted context omitted.
But it is true. My own biggest mistake when learning Rust was that I tried to torce Object Oriented paradigms on it. That went.. poorly. As soon as I went "fuck it, I just do it like you want" things went smoothly.
Sounds like an abusive relationship if im being honest. Your programming language shouldnt constrict you in those ways.
Flattening Rust’s learning curve
371–380 of 405 posts
Re: Flattening Rust’s learning curve
#372Earlier quoted context omitted.
> Why can mutable reference be only handed out once? Here's a single-threaded program which would exhibit dangling pointers if Rust allowed handing out multiple references (mutable or otherwise) to data that's being mutated: let mut v = Vec::new(); v.push(42); // Address of first element: 0x6533c883fb10 println!("{:p}", &v[0]); // Put something after v on the heap // so it can't be grown in-place let v2 = v.clone();…
> // Put something after v on the heap > // so it can't be grown in-place > let v2 = v.clone(); I doubt rust guarantees that “Put something after v on the heap” behavior. The whole idea of a heap is that you give up control over where allocations happen in exchange for an easy way to allocate, free and reuse memory.
Re: Flattening Rust’s learning curve
#373Earlier quoted context omitted.
> Why can mutable reference be only handed out once? Here's a single-threaded program which would exhibit dangling pointers if Rust allowed handing out multiple references (mutable or otherwise) to data that's being mutated: let mut v = Vec::new(); v.push(42); // Address of first element: 0x6533c883fb10 println!("{:p}", &v[0]); // Put something after v on the heap // so it can't be grown in-place let v2 = v.clone();…
The analogous program in pretty much any modern language under the sun has no problem with this, in spite of multiple references being casually allowed. To have a safe reference to the cell of a vector, we need a "locative" object for that, which keeps track of v , and the offset 0 into v.
And then every time the underlying data moves, the program's runtime either needs to do a dynamic lookup of all pointers to that data and then iterate over all of them to point to the new location, or otherwise you need to introduce yet another layer of indirection (or even worse, you could use linked lists). Many languages exist in domains where they don't mind paying such a runtime cost, but Rust is trying to be as fast as possible while being as memory-safe as possible.
In other words, pick your poison:
1. Allow mutable data, but do not support direct interior references.
2. Allow interior references, but do not allow mutable data.
3. Allow mutable data, but only allow indirect/dynamically adjusted references.
4. Allow both mutable data and direct interior references, force the author to manually enforce memory-safety.
5. Allow both mutable data and direct interior references, use static analysis to ensure safety by only allowing references to be held when mutation cannot invalidate them.
Re: Flattening Rust’s learning curve
#374It took me a few tries to get comfortable with Rust—its ownership model, lifetimes, and pervasive use of enums and pattern matching were daunting at first. In my initial attempt, I felt overwhelmed very early on. The second time, I was too dogmatic, reading the book line by line from the very first chapter, and eventually lost patience. By then, however, I had come to understand that Rust would help me learn programm…
Your experience matches an observation I have made, that when C++ developers approach Rust for the first time they often "fight the borrow checker" when they use C++ idioms in Rust. Then they start to learn Rust idioms, and bring them back to C++, which causes them to write more robust code despite not having and borrow checking at all.
Re: Flattening Rust’s learning curve
#375It's like reading "A Discipline of Programming", by Dijkstra. That morality play approach was needed back then, because nobody knew how to think about this stuff. Most explanations of ownership in Rust are far too wordy. See [1]. The core concepts are mostly there, but hidden under all the examples. - Each data object in Rust has exactly one owner. - Ownership can be transferred in ways that preserve the one-owner ru…
Coming from that background these rules sound fantastic, theres been a lot of work put into c++ the past few years to try and make these things easier to enforce but it's still difficult to do right even with smart pointers.
Re: Flattening Rust’s learning curve
#376It's like reading "A Discipline of Programming", by Dijkstra. That morality play approach was needed back then, because nobody knew how to think about this stuff. Most explanations of ownership in Rust are far too wordy. See [1]. The core concepts are mostly there, but hidden under all the examples. - Each data object in Rust has exactly one owner. - Ownership can be transferred in ways that preserve the one-owner ru…
The second bullet in the second section is overpromising badly. In fact there are many, many, many ways to write verifiably correct code that leaves no dangling pointers yet won't compile with rustc. Frankly most of the complexity you're complaining about stems from attempts to specify exactly what magic the borrow checker can prove correct and which incantations it can't.
Re: Flattening Rust’s learning curve
#377Rust is wonderful but humbling! It has a built in coach: the borrow checker! Borrow checker wouldn't get off my damn case - errors after errors - so I gave in. I allowed it to teach me - compile error by compile error - the proper way to do a threadsafe shared-memory ringbuffer. I was convinced I knew. I didn't. C and C++ lack ownership semantics so their compilers can't coach you. Everyone should learn Rust. You nev…
Bondage driven development.
Re: Flattening Rust’s learning curve
#378Earlier quoted context omitted.
The second bullet in the second section is overpromising badly. In fact there are many, many, many ways to write verifiably correct code that leaves no dangling pointers yet won't compile with rustc. Frankly most of the complexity you're complaining about stems from attempts to specify exactly what magic the borrow checker can prove correct and which incantations it can't.
Rust feels like an excellent language paired with a beta-quality borrow checker. The issue is that the more they fix the paper cuts, the more complex the type system grows.
Re: Flattening Rust’s learning curve
#379Earlier quoted context omitted.
I think your comment has received excellent replies. However, no one has tackled your actual question so far: > _who_ is the owner. Is it a stack frame? I don’t think that it’s helpful to call a stack frame the owner in the sense of the borrow checker. If the owner was the stack frame, then why would it have to borrow objects to itself? The fact that the following code doesn’t compile seems to support that: fn main()…
I believe this answer is correct. Ownership exists at the language level, not the machine level. Thinking of a part of the stack or a piece of memory as owning something isn’t correct. A language entity, like a variable, is what owns another object in rust. When that object goes at a scope, its resources are released, including all the things it owns.
Right. That's the key here. "Move semantics" can let you move something from the stack to the heap, or the heap to the stack, provided that a lot of fussy rules are enforced. It's quite common to do this. You might create a struct on the stack, then push it onto a vector, to be appended at the end. Works fine. The data had to be copied, and the language took care of that. It also took care of preventing you from doing that if the struct isn't safely move copyable.
C++ now has "move semantics", but for legacy reasons, enforcement is not strict enough to prevent moves which should not be allowed.
Re: Flattening Rust’s learning curve
#380Earlier quoted context omitted.
Cloning doesn’t imply heap allocation. Depends on the type.
If the object had a stack-bounded lifetime, the borrow checker would have been able to prove the analysis though. The advice is to clone things it can't, which pretty much requires that it go into the general heap. I'm sure there are some interesting counterexamples, but the situation you're imagining seems kinda academic.