4 ms·
3. Unlike other languages, variables can be created tied to a scope outer to the one where they are created. The user can control this by indicat
by dbaupp 12y ago
3. Unlike other languages, variables can be created
tied to a scope outer to the one where they are
created. The user can control this by indicating
that the lifetime of a variable is the same as that
of some variable from an outer scope. This is Rust's
big innovation.
This isn't quite right (or I'm not understanding what you're trying to say).
Given
let x = 1;
{
let y = 1;
}
there's no way you can make `y` itself live as long as `x`.
4. The "=" operator usually means "move", and when it does,
the right hand side of the "=" becomes inaccessable.
(This is type-dependent; some types copy when "=" is used.)
This preserves single ownership.
I think this is "complicating" how =/moves work: it's really binding things by-value that are moves, the = operator isn't special. E.g. `foo(x)` will move `x` into the `foo` call, despite there being no `=` at all.
2. You can declare an enum with a data object as a field in a
structure. This creates a structure that contains (really links
to) another data object.
I don't understand this, could you clarify?
- The type system really is complex.
I don't think this is very true, what complexity do you see?
- Animats 12y agoI'd answer this, but I haven't used Rust for three weeks, and the language changed again. None of my programs will compile any more. (Sorry, I'm in a cranky mood about Rust right now. I just had to file an issue on the Hyper HTTP library because some names were just changed in the I/O library, making the HTTP library uncompilable.)
- MichaelGG 12y agoRegarding the first point, about scope, I'd guess he's referring to lifetimes and how you can explicitly annotate that something can live as long as another thing, like a parameter. Not scope exactly.
- Animats 12y agoRight. When you give an object A a lifetime that makes it live as long as object B, you're effectively putting object A into the same scope, for memory allocation purposes, as object B. This works even if B is in an outer scope. This is a new, and very powerful concept. Any tutorial on this needs to be illustrated. Talking about line numbers is not enough.
- dbaupp 12y agoThis... isn't how lifetimes work. As I said above, there's no lifetime annotations you can use to ensure that y lives as long(aka is in the same scope) as x in the following let x = 1; { let y = 2; } This is also true if you do dynamic allocations: there's fundamentally no way to "promote" variables to a higher scopes just by using lifetime annotations. Lifetimes are a purely passive thing, designed to allow the compiler to check the programmer's use of references, not to allow the compiler to massage things around to ensure that whatever use work. That is, if a Rust program compiles, then it will also compile (modulo needing extra `unsafe` annotation) and, importantly, do the same thing, if all the references are replaced with raw pointers, which don't have lifetimes to describe their relationships.
- Animats 12y agoYou're right. I thought you could use lifetime annotation to force something to be allocated in an outer scope. But Rust doesn't allow that.
- dbaupp 12y agoI sounded to me like Animats was describing an "active lifetime" system, where the compiler will change where variables are placed, when they are deallocated (etc.) to make whatever code work. Rust's lifetimes do not work like that.
- iopq 12y agoI think traits are really confusing (dispatch by input AND output type), there's also trait inheritance, trait bounds, casting things to traits; add type inference to that, lifetime parameters and generics. You get things like struct Foo<'a, P> where P: std::ops::Neg + 'a, <P as std::ops::Neg>::Output: 'a { foo: &'a Bar<P>, } after further research this makes sense, of course, but looks like non-sense to anyone just trying to learn the language
- dbaupp 12y agoHm, maybe I just "know too much", but it seems to me that most of the parts of the type system are relatively independent: there's not too many weird interactions between the various parts, and many systems are complex because of the surprising interactions. In any case, half the "complexity" in the example you give is the noise of using the fully-qualified std::ops::Neg path in the bounds, rather than importing it and just writing `Neg`. :)
- baq 12y agoTBH whenever I see type names being added to each other, my brain kind of shuts down the relevant lobes. Granted, I'm barely initiated to Rust, but... it just looks confusing. (It doesn't help that it's not actually type names, but a type name and a lifetime...)
- pcwalton 12y agoI've seen this example several times now, and I never got why it was so bad: it's mostly an objection to the namespace qualification syntax if anything. It would actually be written: use std::ops::Neg; struct Foo<'a,P> where P: Neg + 'a, <P::Neg>::Output: 'a { foo: &'a Bar<P>, } And with further proposed improvements it would be: use std::ops::Neg; struct Foo<'a,P> where P: Neg + 'a, P::Output: 'a { foo: &'a Bar<P>, } Not bad. It's saying "I have a generic structure over a type parameter P tied to a lifetime 'a, and P must overload the unary minus operator".
- iopq 12y ago