Is there already an article that describes this well?
async traits in std instead of each runtime having their own,
a pluggable interface so that async in code doesn’t have to specify what runtime it’s being built against
potentially an effect system to make different effects composable more easily (eg error effects + async effects) without needing to duplicate code to accomplish composition
Keyword generics as the current thing being explored instead of an effect system to support composition of effects
With these fixes async rust will get less annoying but it’s slow difficult work.
I'm not going to pretend I'm an expert but would be happy if someone could expand further.
* An overview of terminology, and a description of how various languages fit into the various parts of the design space https://www.infoq.com/presentations/rust-2019/
* A deep dive into what Rust does https://www.infoq.com/presentations/rust-async-await/
https://github.com/rust-lang/rfcs/blob/0806be4f282144cfcd55b...
†Yes, there are other differences between goroutines and typical OS threads, such as stack sizes, but I'm only talking about I/O differences here.
For example, the common form of `await` calls implies cooperative multitasking and people will have a good reason to believe that no other tasks can't affect your code between two `await` calls. This is not generally true (e.g. Rust), but is indeed true for some languages like JS. Now consider two variants of JS, where both had `await` removed but one retains cooperative multitasking and another allows preemptitive tasks. They will necessarily demand different mental models, even though it is no longer syntactically distinguishable. I believe this distinction is important enough that they still have to be considered to have a function color, which is only uniform within a single language.
Zig's approach in comparison is often called "color-blind", because while it provides `async` and `await`, those keywords only change the return type to a promise (Zig term: async frame) and do not guarantee that it will do anything different. Instead, users are given the switch so that most libraries are expected to work equally well regardless of that switch. You can alternatively think this as follows: all Zig modules are implicitly parametrized via an implicit `io_mode` parameter, which affect the meaning of `async` and `await` and propagate to nested dependencies. There is definitely a color here, but it's no longer a function color because functions can no longer paint themselves. So I think it's reasonable to call this to have no function color.
[1] https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...
This means, before async existed, any library doing IO had to be based on callbacks. Then came Promises, which are essentially glorified callbacks and then came async which can be seen syntax sugar for Promises.
So you will never see synchronous code that depends on an asynchronous result. The concept of sync code waiting for something just never existed in JavaScript. Instead you wake up your sync functions with Promise.then()-callbacks and that same mechanism bridges async functions.
It’s also very rare to have compute heavy sync code in JS so there is rarely any need to run it multi threaded.
Have you forgotten prompt() and friends?
In Go there's no function coloring because there are only async functions. That's why they don't get any special color, they are the only color. In Go you don't get to use sync functions, which creates problems e.g. when you need to use FFI, because the C ABI is the exact opposite and doesn't have function coloring because it only allows you to use sync functions.
Zig and Rust's async-generic initiative are a bit different in that they want to allow functions to be both sync and async at the same time. Ultimately there are still colors, but you don't have to choose one of them when you write a function. However IMO there are a lot of non-trivial problems to solve to get to that result.
Ultimately Go's approach work well enough, and usually better than other approaches, until you need to do FFI or you need to produce a binary without a runtime (e.g. if you need to program a microcontroller)
If we call the go programming model async, the word has completely lost all meanings.
These days async functions are also typically lazily evaluated via partial evaluation and the return continuation is not necessarily provided at the call site.
A sync function provides it's result via the normal return path.
For typical libraries, functions and structs are provided, and to the extent that these functions call functions provided by the user, they are generic over the async-ness of those functions. That's how the language-level async feature works, for library code that doesn't specify that it is async and doesn't specify that it would like to use a specific non-async calling convention for calling the user's callbacks.
Details which are meant to be ignored. When you use async/await constructs in various languages, you don't care about the fact that they are desugared into callback chains under the hood. You either do async/await in a language or you don't. That's what the concept of 'your function has a colour' means. If you want to change the meaning, OK but then you're talking about something else.