4 ms·
If borrowing is the default, why does it require additional syntactic noise? Why isn't transfer achieved by adding sigils such as "&"?
by spion 12y ago
If borrowing is the default, why does it require additional syntactic noise? Why isn't transfer achieved by adding sigils such as "&"?
- kibwen 12y ago1. Familiarity to C++ programmers, for whom taking a reference via `&` is a familiar operation. 2. There are two different kinds of references: `&` is immutable and `&mut` is mutable. One way or the other you'd need some sort of differentiation. 3. Borrowing, though crucial to the idea of Rust, is still less fundamental than ownership. You can have a language with ownership and without borrowing (indeed, this is how most prior languages with ownership work). But you can't have borrowing without tracking ownership.
- wycats 12y agoAlso, there are a whole host of very common types (integers, etc.) that actually want to be passed by value and copied. There's no point in making a pointer to an integer and then dereferencing the pointer in the callee when an integer fits into the same amount of space as a pointer in the first place. Very simple types (without heap pointers or destructors) can be passed by value and efficiently copied. You end up with a bit of an intuition for "value types" (simple types whose identity is bound up in the shallow memory that they contain). In other GC'ed languages, there is a fixed set of these kinds of values (often called "primitives"). In Rust, any simple user-specified type can be a "primitive".
- Animats 12y agoIf something is immutable (and doesn't own something else), it doesn't matter whether it's passed by value or reference. That's a decision the compiler can, and should, make, as an optimization decision. In Modula, where pass-as-read-only was the default, small items were passed by value and large ones by reference. "Small" is a CPU-dependent optimization and should be left to the compiler, not "user intuition". The default should be pass as read-only reference. If you want a copy of something, you should have to explicitly make one. If you want write access, you should have to say so. Rust has all the right concepts, but the defaults aren't in the safest direction. The experience of "const" in C/C++ teaches us that they should be.
- wycats 12y agoThere is an important distinction in Rust: ownership. Copyable objects are (by definition) simple enough that copying them does not introduce aliasing. Objects with heap pointers or destructors cannot be copied, because now there would be two "owners" of those values. For what it's worth, I've found that a lot of these assumptions ("it doesn't matter, let the compile optimize it") really remove the programmer from important power. And before you find yourself saying "are you saying everyone should write everything in assembler?": 1. There is a distinction between writing code in assembler and having to use a `&` sigil for "by-reference" in a language that has lambdas, traits and many other high-level features. 2. You should generally use Rust for cases where performance characteristics are important, and where control over memory is important. If you're sure it's not important, by all means go with a higher-level language that abstracts it away. I made this point (perhaps more clearly) in my talk at GoGaRuCo: http://www.youtube.com/watch?v=ySW6Yk_DerY http://www.youtube.com/watch?v=ySW6Yk_DerY
- kibwen 12y ago> the defaults aren't in the safest direction Can you elaborate on this? I'm curious to know how you perceive Rust's defaults as unsafe.
- spion 12y agoDoesn't #1 matter less in Rust? C++ has to deal with backward compatibility in syntax, Rust doesn't. Based on this article, immutable references are the most common kind of declarations. It seems to me that rust code would look much cleaner if they had the shortest syntax (including in pattern matching etc)
- kibwen 12y agoRust's primary intended audience is C++ programmers, and familiarity is a powerful asset. It's not the sole determinant of syntax concerns, but it's an important consideration.
- ben0x539 12y agoWell, really the default is passing trivial implicitly-copyable values like integers. You probably don't want to write a & every time you pass an i32 to a function, so that sort of thing gets the default just-passing-bytes-around syntax from other C-like languages. For resources or generally things that require cleaning up when they disappear, that just extends into the transfer, logically a shallow copy with the original variable flagged as dead in the type system. The & symbol denotes a reference type, and it's an explicit thing in the type system and not just an annotation as part of the function call process. It can show up anywhere you'd write a type, things like `Option<&T>` or other types with `&T` fields aren't too uncommon, and `&&T` is also a type. I haven't really thought it through, I guess, but modifying a type `T` with a `&` to make it a pointer type `&T` seems to compose a lot better than making all types `T` implicitly pointers and requiring `&T` whenever you want the value inline and not behind a pointer indirection, whether in a local variable or as a field in a struct.