Dear community, I’m not going to try and rehash any of the other arguments made for all the syntax proposals. I strongly support the process and the team’s leadership up to this point. @withoutboats has done an excellent job communicating the process and the reasons for the decisions, I’m also in favor of .await as the preferred or “least bad” option.
I’ve read through the articles and posts recently and to me the main concern with the .keyword decision seems to be how it surprisingly/magically changes field access into something that you now have to teach as “, this is how field access is done in rust, except for .await which is something you as a beginner will learn about later”. It detracts from “field access” being something that you can bank axiomatically.
Can the team perhaps consider discussing this explicitly, or point to the discussion in the RFC process if this has indeed been carefully considered?
Strong consideration should be given to the impact on brand new users, newcomers or interested parties reading code as a way to get a feel for the language. I’m not arguing for a change, but I for one would happily live with a little extra line noise (as would be the case when a sigil like @ be introduced to the keyword, @await perhaps) if it means protecting Learnability.
All you have to tell new users is that await is a keyword, and keywords are not allowed as field names. You only have to teach them that await is allowed here when they want to use it. Do you expect that new Rust programmers are going to be diving in on await?
That's the primary advantage that I see in the suggestion to use ¡ as that sigil. To ease the typing burden, .await could be permitted as an alternate form that rustfix would canonicalize as ¡await. To my eye, ¡ has almost as little visual noise as . while being obviously different from all other operators.
¡ also has potential as a future low-noise pipeline operator, should the lang team need one in the future. I think such a single-character pipeline sigil could be preferable to the harder to learn (IMO) and more parse-ambiguous |> double-character pipeline sigil used in other languages. The obvious analogy between . for method chaining and ¡ for pipeline chaining makes such a choice attractive to me.
Please make a convincing and serious case why @ is more learnable. This post goes very deep into fuzzy territory, which doesn’t help the subject.
Learnability is considered while deriving changes in Rust, but it is not used as a deciding factor. There’s some hard reasons for that:
There’s almost no research into learnability of programming languages. It would be a huge presumption to argue about it like we know.
If there is research, it mostly points towards syntax not being a large matter.
Most of us are not teachers and those of us who teach have experiences that match the above
Even if one teacher finds something difficult to teach, there’s always the possibility that the error is on the teachers side.
Words like “magical” are not useful to discussions. What’s magical or not is very much up to personal reading and every option of await is magical in the sense that it does something that straight Rust code cannot.
As someone who teaches Rust on an almost monthly basis since 2016, i have a couple of opinions:
await is a recognizable word that is rarely used as variable name or field.
await in any form has clear, but complex semantics, which are much more important then the syntax
await, when seen, cannot be confused, as there cannot be a field or method of that name
await is grepable, @ is not (as it is used in match patterns)
people with experience in a language often have a harder time learning new behaviour than people how start out
people who learn programming languages are very effective in learning “this is how you do things” just straight away
Finally, I have the following personal opinions:
Missing an await point during reading isn’t dangerous.
If you miss it, but you care, you will find it during close inspection easily
Programmers train finding code patterns for review very quickly, await pops out as much as “unwrap” or other ways
Reading comprehension research points to humans being extremely good at finding words by patterns and length, unless you have a problem there, in which I don’t see how any of these methods would be better or worse.
The point is that:
A rule without exceptions is easier to learn and internalise than a rule with exceptions.
Definitive rules (that just "are"), are much easier to learn than things that are "except`when".
I might not teach rust and be able to roll out my long list of credentials, but ask any child learning English about the rule when "i" follows "e".
The opportunity is that something like @await (even though it is perceived to be "line noise") becomes a standalone rule, not an exception to the .field field access rule.
You did mention that you don't have a lot of time, so I don't want to keep you much longer, but feedback was solicited. The community isn't trying to defend a thesis, they are merely answering the team's request for feedback/opinions.
I don’t think learnability is the real issue here. To me, the syntax is just inconsistent with the rest of the language. It’s not hard to learn or teach, but it’s like saying "let’s get rid of the braces and make Rust whitespace-sensitive, but only in match". Or adding an S-expression sub-language. Or anything like that.
The problem I have with this statement is that it suggests that there is some other syntax that is more consistent. Hitherto, I have not found one that is. And we haven't talked about other important aspects as well beyond consistency.
Awaiting is a really funky operation. It doesn’t have any reason to be consistent with the rest of the language when what it does is so unique. (And that problem will completely solve itself as soon as some await syntax becomes an actual part of the language.)
And consistency assists learning and retention, it make it easier to internalise rules and build mastery. The borrow checker consistently makes you write memory safe code, unless, consistently you opt out using ‘unsafe’.
I agree very much.
Prefix await and await!() are consistent with the rest of the syntax of Rust. They may be awkward to use in some specific cases, but inconsistent they are not.
So are throw and catch in languages with exceptions. So is call/cc in Scheme. They do something funky, but their syntax is consistent with the rest of the language.
That's a tautology.
Anyway, I don't want to argue against postfix await -- I did enough of that already. I just wanted to mention that I don't believe learnability to be the main reason why some people dislike it so much.
What is await expr consistent with? break expr and return expr (the only unary prefix keyword operators)? -- Those are both typed at ! whereas await expr typically isn't. If you are going to argue that this is consistent, then I think that's quite a shallow syntax-only consistency. The notion of await is semantically most alike ? and so it is consistent for it to be postfix.
Meanwhile, await!(..) has consistency with nothing because 1) try!(..) is deprecated, 2) it cannot be a macro in the semantic sense.
Yes, I am referring to the syntax (I wrote exactly that in my post above), which happens before any type checking. It's also the first thing someone sees when learning a language.
Perhaps. A sigil would be syntactically consistent, then. I wouldn't want a postfix sigil for await, but I wouldn't argue against it on the point of consistency. But I'm not convinced that await is like ?. It might as well be a function call, like in generators or coroutines. To me, it's most similar to yield, which I hope Rust will get in the future, hopefully not as a postfix keyword (though there will be a precedent then).
Is panic! a macro? Is it a control flow operator? Is it fundamentally different from await because it returns !? await!was implemented as a macro, even though there might have been issues with the quality of the diagnostics.
I would just like to point out that I’m referring to consistency with the rest of the language, especially field access, a predictable, learnable rust is what I’m advocating for, and trying to draw attention to.
I’m very ok with not going with the function or macro syntax.
IMO, the worst thing about .await syntax is that it’s misleading. Many programmers who already know Python, C# or JavaScript also know that await is the prefix operator, and when they see future.await the first thing that would come into their minds is that Rust just have a different way to write await future and that something.if, another.match, etc. also should be possible. These words in some degree could be proven after reading the final proposition for “await” syntax thread which is full of proposals to extend . operator to work like that.
It seems that your concern, and that of many others, is that the dot (.) may be confusing to programmers with experience using await in other languages. If so, what is wrong with the proposal to change the sigil before await to ¡? (FYI, that’s entered as OPT+! on my Mac keyboard.)
That sigil change could be made at any time; it is not required before stabilizing postfix .await. So if real-world experience demonstrates that this currently-hypothetical confusion is a real problem, or if another RFC proposes to generalize .keyword syntax, an RFC to change the keyword-preceding sigil and deprecate . for such use can be made at that time.
Is that not true of many other characters that Rust uses that are absent from the majority of non-English European keyboards, plus all the keyboards in the world that are used with non-Roman character sets? For example, many European keyboards are missing some or all of [, ], {, }, |, #, $.