Hacker News new | ask | show | jobs
by nstbayless 993 days ago
I assume it's this:

In Python, coroutines cannot yield from within another function call: if coroutine A calls function B, B cannot yield. In Lua, it's possible to yield a coroutine at any function depth: B can yield.

To implement something like this in a compiled language, you just need multiple stacks instead of the usual 1. Most architectures, such as x86, have a stack pointer register; when yielding a coroutine, just change the sp register to point to some other stack -- when resuming, restore the sp.

This is not a new concept. Pokémon on the gameboy did this for its UI fiber, for example.

1 comments

> In Python, coroutines cannot yield from within another function call: if coroutine A calls function B, B cannot yield.

I know you likely know this, but just for context. This is technically correct of course, B cannot yield, but not how you would use it in real life. If B needs to yield because it calls C which need to yield, then B needs to be a coroutine itself. This allows for a ‘nested yield’ where A, B, and C are all paused by yielding to their direct parent. Python made this explicit before async/await as you had to use “yield from” instead of just yield. With async/await that became “await”.

This does lead to what’s typically mentioned as the biggest disadvantage of stackless coroutines which is that you get parallel sets of functions, one async and one sync. This mostly means that IO and networking libraries end up being either sync or async but not both.