I answered the quiz and it said "you must be a Javascript developer", which is true enough - that's probably my second-most-proficient language. In fact, I'm a Ruby developer partially because I hate the idea of async/await and I'm feeling very smug about my choice after reading this.

Some of these design decisions seem indefensible to me. For example, what the authors call "Suspension":

-> Static: Await points guaranteed to suspend -- JavaScript

-> Dynamic: No guarantees on awaiting tasks -- C# · Swift · Tokio · Smol · Asyncio · Trio

What is "await" if not a synonym for "suspend"?!?

async/await is one product of a long line of thought that says "threads are too hard for programmers to get right". Threads (really, shared memory) have real usability issues for developers, but once you grok the semantics (which largely map to the physical execution model in a CPU) that knowledge is transferrable across virtually all languages and runtimes.

> async/await is one product of a long line of thought that says "threads are too hard for programmers to get right".

Having used both threads and async/await and using them both in the same program, I don't see how async/await is supposed to make it easier to get right.

In my experience, async/await seems to be a solution to avoid running too many threads. In Javascript, because you could only have one thread in browsers; in other languages because thread per X is too many threads and queuing to a thread pool might not be desirable either.

Async/await always feels terrible to use though. Some other way to get thread like semantics without having to have OS threads for everything seems better (to me). Erlang processes, Java Loom Virtual Threads (which I haven't used), etc. If it avoids having all memory shared, even better.

In the 1990s, threads were programmed with extensive use of semaphores and threads arbitrarily running around shared data structures. This is a disastrous approach to threading, and I agree with pretty much every scathing condemnation written about it.

The problem is, the community collectively decided the problem was "threading" in general rather than "trying to have tons of threads running around shared data structures controlled via piles of simultaneously-held semaphores" specifically.

If you don't structure your threads on that basis, but instead default to something that looks more like actors and message passing, even if it isn't strictly speaking actors and message passing, the complexity comes down. Add some later elaborations like structured concurrency and a few other pre-canned design patterns for threading like a parallel map or worker pools being issued work items and it becomes merely something difficult rather than insane. When you program with threads sanely, it takes very little for async/await to actually be the substantially more complicated and difficult-to-understand choice when you have a workflow more interesting than "always await everything immediately" to implement, to say nothing of how nice it is to have things actually running on multiple cores simultaneously without having to carefully arrange for it.

Linux has 8MB thread stacks by default, Windows apparently has 1MB ones, and that space is not going anywhere. As long as people are worried about memory, they will need something lighter than threads. (Yes, golang managed to create dynamic stacks, but this required major support from compiler and so unlikely to appear in existing languages).

Also, I think that single-threaded programs, even with co-routines, are just so much nicer than multi-threaded ones. You write "index = last_index++;" and it Just Works (tm), no need to worry about locks or atomics or other thread access.

The principal difference between dispatching in a thread-based framework and async/await is that async/await allows you to program sequences of asynchronous operations much more easily. No more separation of code that initiates an async operation and the code that handles the result!

These higher level primitives that they mention provide the primitives for exactly that. This can be found in other paradigms besides async/await.

I do find that the ergonomics of this are highly dependent on a few features of a language runtime, without which it all falls apart. Or you need language specific syntax and typically a single standard implementation.

The principal difference between threads and async/await has to be specified in at least 9 dimensions...

Very similar dimensions also apply to threads, the async/await is not really that different there.

> What is "await" if not a synonym for "suspend"?!?

The `await` keyword in most languages is not a synonym for suspending thread execution so much as it is an effectual attempt to replicate the functionality of `coreturn`[0]. To wit, if an underlying `Future`/`Promise` has completed before the `await` instruction is evaluated, the thread executing same will not be suspended.

0 - https://www.euclideanspace.com/maths/discrete/category/highe...

> What is "await" if not a synonym for "suspend"?!?

There are scenarios where something might need to await and might not. Why take the hit if you are able to do something synchronously? Edit: this is especially important given the “viral” nature of colored functions.

It does make it hard to reason about, but this kind of problem is all over the place - e.g. very similar-looking code can have very different semantics depending on your framework if you’re using jsx or a particular decorator means one thing in one project and something else in another. That’s just part of the game at this point.

C# has Task.FromResult(), which is useful if you are implementing an interface that allows async work but your implementation doesn't require it. I believe the runtime will check for this case and continue execution. It's better for the cache to keep executing the current task on the current thread.

I don't really understand gp's point. From inside the code, you can't tell if there was a pause or not. Clock time or thread id are heuristics, but you can't really be sure.

> What is "await" if not a synonym for "suspend"?!?

it's a question of whether the runtime is guaranteed to suspend at an await point or if it may choose not to

> async/await is one product of a long line of thought that says "threads are too hard for programmers to get right".

what? no! concurrency vs parallelism etc etc

I'm teaching async calls in makearcade to my 10yo son, to bypass a platform bug. He said he doesn't get it. My answer was: Don't worry, adults don't get it either.