4 ms·
I don't understand, why is "&" not the default and passing ownership something you must explicitly request ? It seems the latter is more common than the former
by BiteCode_dev 4y ago
I don't understand, why is "&" not the default and passing ownership something you must explicitly request ?
It seems the latter is more common than the former, and that would avoid to have to add "&" everywhere.
- emschwartz 4y agoOoh that's a fun question. I think it comes from reusing the C/C++ notation for references (https://stackoverflow.com/a/2094715/2242866 https://stackoverflow.com/a/2094715/2242866). But I have no idea where the original idea for using those characters came from. There's one other thing in Rust that would be kind of difficult if passing a reference were the default, rather than the owned value. Rust has implicit returns so the last thing at the end of a block or function is returned. If you needed to explicitly ask for ownership, you'd need to do that at the end of every function. Also, Rust will yell at you if you try to have a function return a reference to a value that's going to be dropped.
- JohnFen 4y ago> I think it comes from reusing the C/C++ notation for references (https://stackoverflow.com/a/2094715/2242866 https://stackoverflow.com/a/2094715/2242866). But I have no idea where the original idea for using those characters came from. In C++, I think that the use of '&' came from the use of '&' in C as meaning "the address of". A reference and an address to a value are similar concepts.
- Joeboy 4y agoI think it's, um, borrowed from C++'s pass by value / reference syntax. To be honest I'm still a bit muddled about how &x in Rust relates to &x in C++.
- jeremyjh 4y ago& is about the same as const & in C++, just swapping the default for immutability.
- justinpombrio 4y agoOne reason is that "&" is nestable, but ownership is just ownership. Currently the types are: owned T T ref of T &T ref of ref of T &&T You're suggesting that instead you skip the "&" and write some sigil for owned types, say "@": owned T @T ref of T T ref of ref of T ??? How do you write the type "ref of ref of T"? On its own this isn't a super compelling argument, because "&&T" is an unusual type that one doesn't normally use. But it hints at the fact that "&" is a modifier. The stronger but less pithy version of this argument is that if you have a type parameter "T" it's essential that it can be instantiated as "T=&U" for some "U". EDIT: come to think of it, you don't often write "&&T", but it is commonly used. If you `println!("{}", x)` where "x" is a reference, the "println!" macro also takes a reference and you get a "&&" type.
- unshavedyak 4y ago> come to think of it, you don't often write "&&T", but it is commonly used. If you `println!("{}", x)` where "x" is a reference, the "println!" macro also takes a reference and you get a "&&" type. Yup, i see them all the time in iterators too. Eg `foos.iter().filter(|t| ..` `t` is `&&Foo` in that example, iirc. Not that you usually see it though, due to closures obscuring types.
- BiteCode_dev 4y agoYou would use an explict "&", just that &T is implicit by default. I have to assume rust creators knew what they were doing since they are obviously way more experienced at this than me, but I still don't get it.
- justinpombrio 4y agoI suspect you're not imagining all the places this would touch the language. For example: - Does "i32" mean an integer or a reference to an integer? You almost always want it to be an integer, so maybe we carve out an exception for small primitive types, that they don't get an implicit "&". - Likewise some library-defined types like "Rc<T>". "Rc<T>" is the way you store a ref-counted T. So you usually want "Rc<T>" instead of "&Rc<T>". Is there an exception for this type, too, or do you always have to write "@Rc<T>"? It's defined in the standard library, so if it gets an exception than there has to be a language mechanism for "types that should not have an implicit &". - The ".next()" method on iterators has the type signature "next(&mut self) -> Option<T>", where "T" is the type of the iterator's elements. Under your proposal, you'd write "next(&mut self) -> Option<@T>". If "T=&str", then you're returning an "Option<@&str>". Which has to be equal to "Option<&str>" or else everything breaks, but that might not be super intuitive to programmers. That last one's the most important, though I don't know how to explain it clearly. If you have a type parameter "T", then "T" does not mean owned T. It means "T", whatever "T" is. If "T" is a reference, then it's a reference. And if you have a type parameter "T" then "&T" means a reference to "T" whatever "T" is. If "T" is itself a reference, then "&T" is a reference to a reference.
- downvotetruth 4y agoIt's simpler to buy any true value option than pick from all the rental properties in the rust belt.
- BiteCode_dev 4y agoOh, so it's for performance reason: the default choice is not the easiest, the the cheapest, and they force you to be explicit about paying the price of a reference?
- sebbyy 4y agoBecause Rust is pass by value. f(&s); is practically equal to let r = s.borrow(); f(r);
- BiteCode_dev 4y agoIf I ask why is the sky blue, telling me because blue is the color or the sky doesn't help.
- pornel 4y agoRust 0.x used to have this the other way around with an explicit `move` keyword. It was tedious and eventually dropped. For example, it's more natural to move in assignment. `= move` is weirdly boilerplatey, `=` borrowing is unhelpful, and `=` moving without the move keyword is inconsistent. Also the moment something is borrowed starts a lifetime scope, which is useful to know. It'd be harder to notice loan scopes of loans were implicit.
- emschwartz 4y agoFascinating! Didn't know that