Support for coroutines in Lua is provided by functions in the coroutine
table, primarily create
, resume
and yield
. The developers describe these coroutines as stackful, first-class and asymmetric.
Coroutines are also available in Python, either using enhanced generators (and yield from
) or, added in version 3.5, async
and await
.
How do coroutines in Python compare to those in Lua? Are they also stackful, first-class and asymmetric?
Why does Python require so many constructs (async def
, async with
, async for
, asynchronous comprehensions, ...) for coroutines, while Lua can provide them with just three built-in functions?
Coroutines are blocks of Lua code which are created within Lua, and have their own flow of control like threads. Only one coroutine ever runs at a time, and it runs until it activates another coroutine, or yields (returns to the coroutine that invoked it).
Coroutines work cooperatively multitask by suspending and resuming at set points by the programmer. In Python, coroutines are similar to generators but with few extra methods and slight changes in how we use yield statements. Generators produce data for iteration while coroutines can also consume data.
Python's generator functions are almost coroutines – but not quite – in that they allow pausing execution to produce a value, but do not provide for values or exceptions to be passed in when execution resumes.
Coroutines are Generators, but their yield accepts values. Coroutines can pause and resume execution (great for concurrency).
The simple answer is that they are different languages. Yes, Python coroutines are stackful, first-class and asymmetric. See this answer: Coroutine vs Continuation vs Generator
From the Lua documentation:
Some people call asymmetric coroutine semi-coroutines (because they are not symmetrical, they are not really co). However, other people use the same term semi-coroutine to denote a restricted implementation of coroutines, where a coroutine can only suspend its execution when it is not inside any auxiliary function, that is, when it has no pending calls in its control stack. In other words, only the main body of such semi-coroutines can yield. A generator in Python is an example of this meaning of semi-coroutines.
Unlike the difference between symmetric and asymmetric coroutines, the difference between coroutines and generators (as presented in Python) is a deep one; generators are simply not powerful enough to implement several interesting constructions that we can write with true coroutines. Lua offers true, asymmetric coroutines. Those that prefer symmetric coroutines can implement them on top of the asymmetric facilities of Lua. It is an easy task. (Basically, each transfer does a yield followed by a resume.)
Also, see this discussion on Python's developer mail list: PEP 492: What is the real goal?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With