async/await came out of C# (well at least the JS version of it).
There are a bunch of use cases for it outside of implementing concurrency in a single threaded runtime.
Pretty much every GUI toolkit I've ever used was single threaded event loop/GUI updates.
Green threads are a very controversial design choice that even JVM backed out of.
Yep and I loved when C# introduced it. I worked on a system in C# that predated async/await and had to use callbacks to make the asynchronous code work. It was a mess of overnested code and poor exception handling, since once the code did asynchronous work the call stack became disconnected from where the try-catches could take care of them. async/await allowed me to easily make the code read and function like equivalent synchronous code.
> async/await came out of C# (well at least the JS version of it).
Not sure if inspired by it, but async/await is just like Haskells do-notation, except specialized for one type: Promise/Future. A bit of a shame. Do-notation works for so many more types.
- for lists, it behaves like list-comprehensions.
- for Maybes it behaves like optional chaining.
- and much more...
All other languages pile on extra syntax sugar for that. It's really beautiful that such seemingly unrelated concepts have a common core.
I knew someone was going to bring up monads that's why I put JS version :) JS took the C# syntax.
Similarly F#'s computation expressions predate C#'s syntax, and there is some evidence that C# language designers were looking at F#'s computation expressions. Since the Linq work, C# has been very aware of Monads, and very slow and methodical about how it approaches them. Linq syntax is a subtly compromised computation expression and async/await is a similar compromise.
It's interesting to wonder about the C# world where those things were more unified.
It's also interesting to explore in C# all the existing ways that Linq syntax can be used to work with arbitrary monads and also Task<T> can be abused to use async/await syntax for arbitrary monads. (In JS, it is even easier to bend async/await to arbitrary monads given the rules of a "thenable" are real simple.)
> use async/await syntax for arbitrary monads. (In JS, it is even easier to bend async/await to arbitrary monads given the rules of a "thenable" are real simple.)
I tried once to hack list comprehensions into JS by abusing async/await. You can monkey patch `then` onto Array and define it as flatMap and IIRC you can indeed await arrays that way, but the outer async function always returns a regular Promise. You can't force it to return an instance of the patched Array type.
> Green threads are a very controversial design choice that even JVM backed out of.
Did they? Project Loom has stabilized around Java 21, no?
Virtual Threads aren't quite the same as green threads (they don't block the OS thread) and they work extremely well now.
They are not even remotely the same, there is no reason to compare them at all.
That's interesting because I remember people talking about Rust green threads as M:N mapping, which seems to be the only difference.
I stand corrected, I stopped keeping track of JVM years ago, was referring to initial green threads implementation.