←back to thread

320 points willm | 2 comments | | HN request time: 0s | source
Show context
xg15 ◴[] No.45107259[source]
I learned about the concept of async/await from JS and back then was really amazed by the elegance of it.

By now, the downsides are well-known, but I think Python's implementation did a few things that made it particularly unpleasant to use.

There is the usual "colored functions" problem. Python has that too, but on steroids: There are sync and async functions, but then some of the sync functions can only be called from an async function, because they expect an event loop to be present, while others must not be called from an async function because they block the thread or take a lot of CPU to run or just refuse to run if an event loop is detected. That makes at least four colors.

The API has the same complexity: In JS, there are 3 primitives that you interact with in code: Sync functions, async functions and promises. (Understanding the event loop is needed to reason about the program, but it's never visible in the code).

Whereas Python has: Generators, Coroutines, Awaitables, Futures, Tasks, Event Loops, AsyncIterators and probably a few more.

All that for not much benefit in everyday situations. One of the biggest advantages of async/await was "fearless concurrency": The guarantee that your variables can only change at well-defined await points, and can only change "atomically". However, python can't actually give the first guarantee, because threaded code may run in parallel to your async code. The second guarantee already comes for free in all Python code, thanks to the GIL - you don't need async for that.

replies(6): >>45107307 #>>45107536 #>>45108908 #>>45109368 #>>45110090 #>>45112261 #
int_19h ◴[] No.45109368[source]
Generators are orthogonal to all this. They are the equivalent of `function*` in JS. And yes, they are also coroutines, but experience has shown that keeping generators separate from generic async functions is more ergonomic (hence why C# and JS both do the same thing).
replies(1): >>45109459 #
1. xg15 ◴[] No.45109459[source]
True. I think the connection is more a historical one became the first async implementation was done using generators and lots of "yield from" statements AFAIK.

But I think generators are still sometimes mentioned in tutorials for this reason.

replies(1): >>45109604 #
2. int_19h ◴[] No.45109604[source]
Implementing what was essentially an equivalent of `await` on top of `yield` (before we got `yield from` even) was a favorite pastime at some point. I worked on a project that did exactly that for WinRT projection to Python. And before that there was Twisted. It's very tempting because it gets you like 90% there. But then eventually you want something like `async for` etc...