> is very different to other well-known implementations (C# and JavaScript [...]). Instead of 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, Rust instead uses a generator/coroutine transform to turn the function into a state machine. C# async/await is also very much resumable state machines
Inside Rust's Async Transform
11–20 of 84 posts
Re: Inside Rust's Async Transform
#12Earlier quoted context omitted.
One difference that may exist is that in Rust, async fns don’t immediately execute, they simply create one of these values. I forget if JS and C# do something different, that is, the execute up until the first suspend point. This was one of the major design decisions we’ve made that’s different than other languages.
No you're correct, C# async/await synchronously executes up to the first yield point. In general the tasks are 'hot' in C#, as opposed to F#'s 'cold' Async type.
The pattern-based implementation of `await` is, in my view, the coolest part of the async/await feature set.
Re: Inside Rust's Async Transform
#13Earlier quoted context omitted.
One difference that may exist is that in Rust, async fns don’t immediately execute, they simply create one of these values. I forget if JS and C# do something different, that is, the execute up until the first suspend point. This was one of the major design decisions we’ve made that’s different than other languages.
No you're correct, C# async/await synchronously executes up to the first yield point. In general the tasks are 'hot' in C#, as opposed to F#'s 'cold' Async type.
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).
Re: Inside Rust's Async Transform
#14Earlier quoted context omitted.
No you're correct, C# async/await synchronously executes up to the first yield point. In general the tasks are 'hot' in C#, as opposed to F#'s 'cold' Async type.
That’s true for `async` methods, but keep in mind that you can `await` any value in C# that implements the ‘awaitable’ pattern. A custom ‘awaitable’ can perform its own scheduling however it likes, including when it begins its execution. The pattern-based implementation of `await` is, in my view, the coolest part of the async/await feature set.
Re: Inside Rust's Async Transform
#15Doesn't both JS (via Babel) and C# implement asynchronous functions as state machines in a similar fashion?
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).
Re: Inside Rust's Async Transform
#16> is very different to other well-known implementations (C# and JavaScript [...]). Instead of 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, Rust instead uses a generator/coroutine transform to turn the function into a state machine. C# async/await is also very much resumable state machines
Re: Inside Rust's Async Transform
#17Doesn't both JS (via Babel) and C# implement asynchronous functions as state machines in a similar fashion?
One difference that may exist is that in Rust, async fns don’t immediately execute, they simply create one of these values. I forget if JS and C# do something different, that is, the execute up until the first suspend point. This was one of the major design decisions we’ve made that’s different than other languages.
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.
Re: Inside Rust's Async Transform
#18> is very different to other well-known implementations (C# and JavaScript [...]). Instead of 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, Rust instead uses a generator/coroutine transform to turn the function into a state machine. C# async/await is also very much resumable state machines
Re: Inside Rust's Async Transform
#19Doesn't both JS (via Babel) and C# implement asynchronous functions as state machines in a similar fashion?
Yes, Babel's transform of `async` to ES5 is similar. It turns has to turn a function into a state machine. Rust goes a step further and turns the entire chain of futures into one large combined state machine. 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.…
Re: Inside Rust's Async Transform
#20I got lost in the weeds fairly quickly with this blog post, why is it that you didn't have to implement Future? Pinning is required here because your AsyncRead read_to_end returns a future bound by some reference lifetime?
Yep, the generator created by quote_encrypt_unquote is creating internal self-references from the future created by read_to_end into the AsyncRead it's storing in its environment, while this is happening the AsyncRead must not move and therefore the generator must not move, which is what pinning represents.