3 ms·
I'm not sure I understand why, in design terms, add_first_element doesn't return ownership of the vectors given that they don't seem to be passed in mutably?
by Symmetry 10y ago
I'm not sure I understand why, in design terms, add_first_element doesn't return ownership of the vectors given that they don't seem to be passed in mutably?
- idsout 10y agoOne reason that comes to my mind is more control over resources. You can be sure the memory allocated for the two vectors in main is freed in add_first_element.
- Symmetry 10y agoBut if ownership was returned then it could be freed in main. And because it was allocated on the stack in the first place there doesn't seem to be any reasonable way for the callee to, say, return a reference to an element of the vector because then the caller could return that reference again but then you'd have a value still referred to by the outside context sitting where the stack should be able to grow so I assume that Rust would disallow this and force you to make a copy of anything you want to return.
- pornel 10y agoIt's by design - this syntax intentionally expresses such contract. As a matter of policy Rust doesn't try to figure out behavior of functions from their bodies, because that would mean changes in the implementation could accidentally break the API. While in this example taking ownership is pointless, there are cases where it's meanigful: e.g. a method that closes a file handle would take ownership of the handle to ensure that the handle can't be used anywhere else after it's closed. In Rust ownership allows mutability (if you own an object, and there are no other references to it, you can do whatever you want to it).
- Symmetry 10y agoWouldn't closing a file handle be an action requiring mutability? If the file handle is just a integer then it would be copyable and ownership wouldn't come up as an issue meaning discussions of safety would be moot. I understand not trying to look at function bodies but the mutability of a function seems to be strictly a property of it's type signature. But I think what really bothers me is that whether a value is actually passed to a function by pointer or by copying it onto the stack is governed by whether it has the 'copy' trait - not something obvious to the casual reader of the program. Silently converting what looks like a pass by value call to an in-practice pass by reference based on a trait definition elsewhere in the code base just seems excessively magical to me and I'd be much happier if the compiler threw an error at let answer = add_first_element(v1, v2); because pass by value requires the copy trait which Vecs v1 and v2 don't have.
- masklinn 10y ago> Wouldn't closing a file handle be an action requiring mutability? Closing a file requires ownership and is actually an RAII action: when the file object itself goes out of scope (which by definition means all extant references have been removed) the handle is closed. > But I think what really bothers me is that whether a value is actually passed to a function by pointer or by copying it onto the stack is governed by whether it has the 'copy' trait - not something obvious to the casual reader of the program. That's not correct. The Copy trait means it's semantically copied rather than moved so the original value can still be used, it does not change the technicalities of parameter passing which is always by-value (unless you're explicitly creating a reference) although things may then get optimised differently. > Silently converting what looks like a pass by value call to an in-practice pass by reference There's no such thing. Both Vecs are passed by value. Outside of method calls (which have some syntactic sugar) Rust requires references to be created explicitly. > I'd be much happier if the compiler threw an error at > let answer = add_first_element(v1, v2); > because pass by value requires the copy trait which Vecs v1 and v2 don't have. It has no reason to and it does not. `add_first_element` gets its argument by value, since Vec is not a Copy type v1 and v2 are thus moved into the function and not accessible anymore from outside it.
- Symmetry 10y ago>Closing a file requires ownership and is actually an RAII action: when the file object itself goes out of scope (which by definition means all extant references have been removed) the handle is closed. Ah, no wonder I misunderstood then. I'd forgotten that RAII was something Rust had and that feature does very nicely explain that design decision. I suppose the reason a Vec doesn't implement Copy then is that its members might not, like a file handle?
- masklinn 10y ago> I suppose the reason a Vec doesn't implement Copy then is that its members might not, like a file handle? That is correct, Vec has a pointer to a heap allocated buffer, meaning if Vec were Copy, you'd get two Vec structures for the same backing buffer and that's a recipe for disaster.