But the rest of the event-loop machinery is quite different. JS's async is still fundamentally callback-based. Rust's futures are polled. In JS there's a single global event loop and promises run automagically. In Rust you create futures managed by their executors, each handling its own kind of tasks (CPU pools, network polling).
It could cause code bloat, but in practice these are small functions that get inlined and optimized out to almost nothing (sometimes even the whole struct disappears).
Would you mind elaborating on the polled aspect of rust futures, or link me to some documation? Do you mean that there is a loop polling the result of a future? How does that work with things like select?
We have some really in depth docs in the works here but it’s not quite ready yet.
The pattern-based implementation of `await` is, in my view, the coolest part of the async/await feature set.
Aside: This can be a source of errors in F# code I’ve seen as folks will mix up the cases where they want to result vs running a computation many times. There certainly is plenty of expresivity but in practice it’s a muddier representation (it took me over a year to appreciate this).
Without this, you sometimes had to write a write a wrapper function that does some synchronous setup and returns a Future, which was a bit annoying for stylistic reasons.
There's an interesting but somewhat old discussion here:
https://www.reddit.com/r/rust/comments/8aaywk/async_await_in...
I wonder if anything changed since then? I'm not a Rust programmer so I didn't really understand the article.
I don’t 100% remember, but I think some of the details for us still ended up significantly different. There are so many ways to implement this stuff...
So the performance concern simply does not apply- Rust suspends the same number of times as Dart 2. The race condition concern might, depending on how you look at it, but in return the execution model from within a Future is much more straightforward and predictable.
I found out it works also better together with some other features, like "select!" and the current cancellation mechanics. But I can't remember all the details right away, and it might be pretty hard to explain.
That said the choice makes sense for Rust for those reasons, but is not a general one! I think for Javascript, C# and Dart synchronously executing until the first await point is easier to understand. I e.g. felt that "async" in F# was a bit harder than in C# due to the non immediately executing property.
"... performing a CPS-like transform where an async function is split into a series of continuations that are chained together via a Future::then method"
they are referring to c# and js implementation of promises/futures here