5 ms·
`&` is a reference. `'a` is a label for a memory area, like goto labels in C but for data. You can read it as (memory) pool A. Roughly, when function entered,
by oneshtein 3y ago
`&` is a reference.
`'a` is a label for a memory area, like goto labels in C but for data. You can read it as (memory) pool A. Roughly, when function entered, memory pool is created, then destroyed at exit.
`'static` is special label for static data (embedded constants).
`()` is nothing, like void in C.
`&()` is an reference to nothing (an address) like `void const *` in C.
`&&()` is an reference to reference to nothing, like `void const * const *` in C.
`& 'static & 'static ()` is like void `const * const *` to a built-in data in C.
`& 'a & 'b ()` tells compiler that second reference is stored in pool 'a, while data is stored in pool 'b. (First reference is in scope of current function.)
`_` is a special prefix for variables to instruct compiler to ignore warning about unused variable. Just `_` is a valid variable name too.
static UNIT: &'static &'static () = &&();
fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v }
Let's say that `&'a` is from a function `a()`, while `&'b` is from a function `b()`, which called from the function `a()`.
The trick here is that we relabel reference from pool `'b`, from an inner function, to pool `'a` from outer function, so when program will exit from function `b()`, compiler will destroy memory pool `'b`, but will keep reference to data inside until end of the function `a()`.
This should not be allowed.
- brink 3y agoI think that's the best description of a lifetime I've seen so far.
- dgfitz 3y agoThank you very much for spending time explaining this. It makes more sense with that kind of description. I'm still not sure how long it would take someone like myself to be comfortable and proficient with the syntax. I guess stated another way, I don't generally have issues reading code from a wide swath of languages. If someone plopped me in front of a rust codebase I'd be at the mercy of the manual for quite a long time. Thank you again, sincerely.
- steveklabnik 3y agoRust decided to spend very little budget on syntax. The issue though, is that where it took said syntax from is very wide. & is used for references in a lot of languages. () is a tuple, same syntax as Python 'a isn't even novel: it was taken from OCaml, which uses it for generic types. Lifetimes are generic types in Rust, so even though it's not for an identical thing, it's related enough to be similar. _ to ignore a name for something has a long tradition in programming, sometimes purely as a style thing (like _identifier or __identifier), but sometimes supported by the language. fn name(args) -> {} as function syntax is not SUPER unusual. The overall shape is normal, though the choice between "fn," "fun," "func," or "function" varies between languages. The -> comes from languages like Haskell. <> for generics is hotly debated, but certainly common among a variety of langauges. the "static name: type = value;" (with let instead of static too) syntax is becoming increasingly normalized, thanks to how it plays with type inference, but has a long history before Rust. So this leads to a very interesting thing, where like, it's not so much that Rust's syntax is entirely alien in the context of programming language syntax, but can feel that way unless you've used a lot of things in various places. And that also doesn't necessarily mean that just because it's influenced from many places that this means it is coherent. I think it does pretty good, but also, I'd refine some things if I were making a new language.
- styfle 3y ago> I'd refine some things if I were making a new language. Which parts would you change?
- steveklabnik 3y agoAbout a year ago I wrote this: https://steveklabnik.com/writing/too-many-words-about-rusts-function-syntax https://steveklabnik.com/writing/too-many-words-about-rusts-... I do think there's some good criticism of doing this, though, and so even a year later it's not clear to me it's a pure win. I am sympathetic to the vague calls to action by Aria et al. to improve the syntax for various unsafe features. I understand why we ended up where we ended up but I think overall it was a mistake. I am not sure I agree with her specific proposals but I do agree with the general thrust of "this was the wrong place to provide syntactic salt." (my words, not hers, to be clear) Ideally `as` wouldn't be a thing. Same deal, this is just one of those things that's the way it is due to history, but if we're ignoring all that, would be better to just not have it. I am still undecided in the : vs = debate for structs. I am sad that anonymous lifetimes in structs died six years ago, I think that would be a massive help. Probably tons of other small things. Given the context and history, I think the Rust Project did a great job. All of this is very minor.
- jcranmer 3y agoTo be fair, even for someone who is comfortable in Rust, the example is definitely on the rather confusing side of the language. (Not entirely surprising--it's a bug about a soundness hole in the language, which invariably tends to rely on overuse of less commonly used features in the language). In particular, explicit use of lifetimes tends to be seen as somewhat more of a last resort, although the language requires it more frequently than I like. Furthermore, the soupiest of the syntax requires the use of multiple layers of indirection for references, which itself tends to be a bit of a code smell (just like how in C/C++, T * tends to be somewhat rare).
- mkehrt 3y agoI write rust professionally and really like it, but I do think that its noisy syntax is a flaw. I'm not sure how I would clean this up, but it really can be inscrutable sometimes.
- datadeft 3y agoFor an anecdota it took me roughly a year. I was trying it several times. I still use .clone() a lot but it is getting better. :) The real question what is the use of Rust for you. Do you work on anything where Rust could be a value?
- viraptor 3y ago> If someone plopped me in front of a rust codebase I'd be at the mercy of the manual for quite a long time. This is not a representative sample of Rust. That's explicitly triggering edge cases which requires abuse of syntax you wouldn't normally see. Check out this for something more realistic that anyone should understand https://github.com/ratatui-org/ratatui/blob/main/examples/calendar.rs https://github.com/ratatui-org/ratatui/blob/main/examples/ca...
- stouset 3y agoYou will never actually encounter code like this in practical use. And even if not, this example isn’t particularly hard to decompose and understand once you have a basic grasp of the independent underlying bits (generics, lifetimes, borrows). It’s just combining all of them pathologically into an extremely terse minimal reproduction. It’s like saying you could never understand Java because someone linked to an AbstractClientProxyFactoryFactoryFactoryBean.
- dingi 3y agoIf memory safety needs this level of fuckery to get going, it's not worth it for vast majority of software. Maybe stick to a GCed language until we can come up with a sane way to do it. These examples look cryptic as hell.
- steveklabnik 3y agoIt's cryptic because it is a reduced test case to show off a bug. 99.9% of code doesn't look like this. Just because "int ((foo)(void ))[3]" is a valid C declaration doesn't mean that all of C code looks like that.
- pcwalton 3y agoThis is basically the Rust equivalent of the obfuscated C code contest and indicates little to nothing about the actual Rust people write.
- datadeft 3y ago> this level of fuckery to get going C++ has the same level of fuckery without memory safety. I don't think there is an extreme level of fuckery in Rust. I wish they got more influence from the ML languages than C++ but it is not unbearable.
- 0x457 3y agoIt's a level of fuckery required to trigger a compiler bug. You don't see code like this in real code bases.