Await Syntax Discussion Summary

Speaking from some experience with async/await in C#, my 2 cents on a prefix syntax:

  • Things like (await Foo()).Bar() are reasonably common and somewhat annoying, but you don’t run into that case all the time. There’s also some argument to be made that the forced parentheses highlight the actual control flow.

  • I agree that (await foo())? is too unergonomical for this very common usecase. In C#, all futures are the equivalent of Result<T, Exception>. You can query that by hand, but await automatically unwraps and rethrows the exception (which 99% of the time is what you want). An await? prefix would mostly solve this issue.

  • I don’t remember ever needing more complex chains like await (await Foo()).Bar() or anything similar, though I’m sure there are some cases.

Regarding a postfix syntax:

  • This surprised me given my C# experience, but I find the rationale for a postfix syntax quite convincing, especially because of how well it interacts with ?.

  • foo.await and foo.await() however is just an insidious trap for Rust beginners, if you don’t know what’s going on, nothing about this construct suggests that you’re not looking at a normal field access and instead need to go look for a tutorial. This could be an insane gotcha.

  • That the feature is “called” async/await is IMHO a very weak argument for having an await keyword, Rust isn’t Cobol.

Someone pointed out that with new and unfamiliar features, people tend to err on the side of verbosity. C# is full of examples here (it still has a delegate keyword as an earlier version of what’s now the lambda arrow). People will probably adapt to foo()#? or whatever very quickly.

Of course, taking that heuristic too far and you end up with Perl, so it’s definitely a hard thing to balance.

19 Likes