Does `await` truly need fixing?

One of the listed options in the Paper document is “Mandatory Delimiters”, which is the same as (await foo)? from what I can see. So yes, “fixing” it can mean accepting it as it is in prefix form.

The proposal from withoutboats makes good sense as a middle ground when considering the syntax alone. Given that it’s introducing the dependency of postfix keywords, I’m not sure it should be associated with what has been labelled as an MVP of async/await. Of course, as stated above, adding the proposed syntax at a later date still makes sense.

“Confusing” no, verbose and annoying yes.

I’ll note it’s hard to measure the controversy with a proposal because those in opposition to the proposal are always noisier than those who support it.

It’s done.

8 Likes

The poll has fairly good data on this. See Async / Await syntax straw poll

Personally I have not participated in the poll (and have tried to avoid getting drawn into opinion based discussion about the syntax) because I trust the language team to make a good decision. I know of a few others that are also basically abstaining from the discussion and are happy to go with whatever syntax is chosen. It seems likely that there’s a significant number of people in a similar situation that are not going to appear in any sort of polling.

7 Likes

Of, course. In fact there is a much greater bias, the poll only reflects people actively reading this from. Most users of Rust do not fall into this category. Neither does anyone who will use Rust in the future but has not discovered it yet. It’s always important to keep in mind that most of the users that will use the feature haven’t found Rust yet.

That can be viewed as a further argument for favoring consistency within the language and with other languages, even if that is not favored by the experts and early adopters. However even in this poll there has been a strong preference in that direction.

2 Likes

Anything in the poll, though, is conditional on people having filled out the poll. If “Postfix await proposed for Rust” shows up on Reddit, the probability of someone who prefers prefix then going and filling out the poll is higher than the probability of someone who thinks “yeah, sounds fine” bothering to fill out the poll.

Maybe that is sometimes true, but looking back of the history of the poll (which you can see in my updates in the thread) The percentage of people who like or dislike the .await syntax hasn’t change much. Both before and after the announcement it was not particularly widely liked.

The very first results from the poll had around 25% of people in favor of that syntax and 75% opposed, and it’s less that 1% different from that now. So there hasn’t been any clear change in response to the announcement.

Let’s just link “the other poll” which is more focused on the path to take right now. Currently, it’s “no opinion” > "fut.await first" > "await fut first" > “neither”. (But also only 35 votes so far, so a very small sample size.)

I haven’t really been following this topic, but this syntax looks totally alien to me. Is ‘.await’ a struct field? Some kind of method call without parentheses? Some kind of keyword with a ‘.’ separator? This doesn’t seem intuitive at all, it looks like some kind special case syntax that’s different from Python and JavaScript or anything presently in Rust.

EDIT: Ok, found the longer thread.

I think I see what they’re going for, but it seems like the original proposal has the benefit of working consistently with other languages while being less efficient to work with. Whereas the new proposal is inconsistent with other languages and Rust’s existing syntax patterns, but is more efficient to work with.

That being the case, I’m not sure. Sorry, carry on I guess…

1 Like

“Historical” arguments matter. I’m really disappointed to see this concern dismissed in this way by you, another member of the lang team. Rust exists within a particular historical context, intended to benefit users who exist within that context, having knowledge, biases, expectations, needs, and so on all determined by that context. Imagining that you are designing a platonic language with “intrinsic” properties detached from its context is a deeply flawed, immature design philosophy.

This is much more important than just the syntax for the await operator; we can’t design Rust as if we exist in a vacuum without historical context.

9 Likes

I agree that history and context matters, but they are not everything (not that you suggested that) and I do not read @scottmcm’s comment as a dismissal of the concern as if it had no value at all. For example, in the RFC about reserving try { .. }, Scott makes such a historical argument well. Moreover, I read what Scott says as considering the history of Rust. In other words, “intrinsically” is not some sort of idealistic consideration in this context.

Certainly. A materialist philosophy rather than idealism seems prudent in all aspects of life and that includes language design. However, having a historical analysis is not necessarily the same as an argument by and for tradition. For example, taking history, context, and the user base into account, you may find that we want to do something different than what tradition might argue. To make progress, one also has to break with tradition in some cases.

So yes, learn from history, but don’t necessarily repeat it.

6 Likes

Coming from a javascript / typescript background I’m a little confused why the ? operator wouldn’t be implied automatically by await prefix notation in the first place.

For example, in typescript an async function would look like this:

async function myFunc(): Promise<void> {
    const res1 = await foo();
    const res2 = await bar();
    return res1 + res2;
}

If either calls to foo or bar fail, the top level myFunc function rejects. This passes the error handling up automatically; much like the ? operator in rust does.

Is it because there is actually two Results in a rust future? One for the Future and one for the actual IO operation? If that were the case it seems like it would still be combined into one.

3 Likes

Because futures are not always fallible, so you can’t automatically apply the ? operator.

Also you may want to perform some actions on error before “bubbling” it up, e.g. see usage of context method in Fuchsia async code snippet.

1 Like

await <expression> is the correct syntax for because it is consistent with existing operators that control flow of your code. When I look at it, I see that my code will perform something special with expression, like match or return. And as all of these keyword operators it shall return expression. In case of match it returns expression that returned by each branch of pattern, while await will return Output of Future

In short, awat <expression> which was initial plan in async/await RFC is natural syntax.

What brings .await aside from being work-around for error handling ergonomics? Confusion, community dislike and embarrassment to language. You can argue that we all can get used to it and stop complaining, but in actuality the .await syntax brings nothing to the table aside from easy way to fix some minor problem.

Please do tell me what are benefits of .await syntax comparing to natural await <expression> There was no RFC to adopt .await, it is just suddenly someone decided that Rust should have new weird syntax which is not the same as ?, as .await is not only unfamiliar but it is also contradicting to existing language syntax.

P.s. I must highlight that initial RFC proposed as future await <expression>, not .await, deciding lightly on .await is not something that should be done, considering community expectations from RFC

3 Likes

It did not, it explicitly left the syntax undecided.

7 Likes

It might leave final syntax undecided, but it is pretty much can be assumed as RFC treats it as control flow expression, and the only reason it was left undecided it problem of ?

I read that section as here our idea await <expression> but we need to think about ? so might we modify it a bit like edition brackets and etc. In any case, adoption of syntax should require RFC process

1 Like

Not at all. The future.await syntax idea was raised (invented?) by @scottmcm in the RFC.

As you can see, I was initially skeptical of postfix .await and thought that it should be prefix. Scott provided sound arguments then and I have ever since held postfix in high regard.

6 Likes

His reasoning is at best subjective, there is nothing sound about considering only one use case. The only reasoning for it is to imitate chaining of methods, but then what will become of read-ability?

await is not some simple method invocation, it actually changes the flow of program. I can imagine having few chains of async ops, but I do not believe it would justified something like x.foo().await.bar().await.qa or even .await()

The language syntax should be consistent, and not favoring someone’s personal taste. I like making convenient builders that would allow me to configure something via long chain of method invocations, but I wouldn’t do something like that for multiple async operations. Instead I’d prefer something like

let foo = await x.foo();
let bar = await foo.bar();

bar.qa

You can argue that I can go by with .await, but await <expression> is more natural in Rust as continue, return and other keyword operators await should follow these examples, not ?

P.s. in the end the idea might be raised, but it should be formalized as RFC instead of making it a big surprise to community.

P.s.s I’m pretty sure I’m not alone who thinks of .await as mistake too

4 Likes

I’d like to point out that while there hasn’t been a targeted RFC for await syntax in the RFC repo (which is consistent with the RFC process), there has been and is currently a Request For Comments everywhere else.

Starting (in major effect) with the GitHub issue in January and continuing to withoutboats’s blog announcement and the irlo threads (all of which were advertised on Reddit as well), there have been ample opportunities and Requests For Comments.

The async RFC left the await syntax to be decided as part of stabilization. These multiple threads have requested community comments on the await syntax to inform the lang team’s decision. All putting it in the RFC repository would do is formalize the comments already considered and invite another avenue for people to reintroduce the same exact “opinion” argument (when what the lang team needs to make an objective decision are actual new data to work with).

The system isn’t perfect; no system is perfect. Any bikeshed color will disappoint someone. It’s almost too easy to hold an opinion. But I think in terms of information gathering we’re at a local maximum that’d take more effort to reach a higher one than we’re willing to pay in delays to the MVP shipping of the feature.

4 Likes