I wrote a little further up, but want to circle back as itās less of an impulsive response given Iāve had a few days to think about it. Thereās a lot going on in this thread and people are making good arguments in favour of every suggestion, however there are some specific suggestions which I strongly disagree with.
The first is the sigil form suggested. This is not specifically because I am against the idea, but because there is no obvious symbol to use for this form. The ?
operator for something which could have failed is a logical choice. I have (so far) seen @
, !
and #
suggested in this thread and none of those make any sense with reference to async/await (at least to me). Regardless of if Iām missing something or not, the fact I might be represents that it will be very non-obvious to other users as well. If we do decide on sigils, it should only lead to yet another discussion of which symbol to use - it should not be chosen lightly. This extra overhead makes me against going this route (at least for now).
The other form is the field syntax. If you look at the code foo.await
, itās entirely non-obvious that this could take potentially forever to return. Itās too much of a deviation from what that syntax already represents. Conceptually, once someone has explained it to you, itās not complicated. However I imagine most people will leave with a āthatās kinda grossā feeling. Do not forget that this is meant to be friendly for everyone, including newcomers and intermediates, not only those who are deeply involved with Rust. Not only do I feel it bad in this case, it would also set precedence for a pattern we might not want to continue with.
My initial response was to simply see the syntax of foo.await()
come into play. I donāt see why async/await should be considered anything other than a function call from a developer perspective. The existing Future
in the external crates literally has a foo.wait()
which simply polls continuously. The biggest argument Iāve seen for this (disregarding arguments against postfix in general) is that itās non-obvious that itās doing something asynchronous. I understand this point of view, but would like to point out that just because you have a Future
does not technically guarantee youāre doing something asynchronous.
I still agree with all of this, except that the extra couple of days have given me more time to reflect. As such, I have changed my mind to favour foo.await!()
. It provides a very obvious syntax that can be used for similar features in future, as itās familiar as itās a combination of two existing things - macros and functions. Rather than caring that āitās obvious itās doing something asynchronousā, I now prefer this syntax because itās obvious that itās builtin, in the same way we all use println!
rather than println
. I believe that this syntax strikes a balance between familiarity and ergonomics, and has the added advantage that weāre also deciding the syntax for other features down the road. There are no new symbols required in the language, and thereās no real new concept that you have to learn to move to asynchronous programming.
I do still feel itās a shame that weāre likely to go postfix rather than prefix, as I do like await foo()
, but at this point I havenāt seen anything close to compelling for the prefix case which still solves the initial problem.