How do coroutines in Python compare to those in Lua?
<p>Support for coroutines in Lua is provided by <a href="https://www.lua.org/manual/5.3/manual.html#2.6">functions in the <code>coroutine</code> table</a>, primarily <code>create</code>, <code>resume</code> and <code>yield</code>. The developers describe these coroutines as <a href="http://laser.inf.ethz.ch/2012/slides/Ierusalimschy/coroutines-4.pdf">stackful, first-class and asymmetric</a>.</p>

<p>Coroutines are also available in Python, either using <a href="https://www.python.org/dev/peps/pep-0342/">enhanced generators</a> (and <a href="https://www.python.org/dev/peps/pep-0380/"><code>yield from</code></a>) or, added in version 3.5, <a href="https://www.python.org/dev/peps/pep-0492/"><code>async</code> and <code>await</code></a>.</p>

<p>How do coroutines in Python compare to those in Lua? Are they also stackful, first-class and asymmetric?</p>

<p>Why does Python require so many constructs (<code>async def</code>, <code>async with</code>, <code>async for</code>, <a href="https://www.python.org/dev/peps/pep-0530/">asynchronous comprehensions</a>, ...) for coroutines, while Lua can provide them with just three built-in functions?</p>

<p>I just had my first look at <code>lua</code>, which included the <a href="https://www.lua.org/cgi-bin/demo?sieve" rel="nofollow"><code>sieve.lua</code> live demo</a>. It is an implementation of the sieve of Erathostenes using coroutines. My immediate thought was: This would look much cleaner in python:</p>

<pre><code>#!/usr/bin/env python3

# sieve.py
# the sieve of Eratosthenes programmed with a generator functions
# typical usage: ./sieve.py 500 | column

import sys

# generate all the numbers from 2 to n
def gen(n):
    for i in range(2,n):
        yield i

# filter the numbers generated by `g', removing multiples of `p'
def filter(p, g):
    for n in g:
        if n%p !=0:
            yield n

N=int(sys.argv[1]) if len(sys.argv)&gt;1 else 500 # from command line
x=gen(N)                     # generate primes up to N
while True:
    try:
        n = next(x)          # pick a number until done
    except StopIteration:
        break
    print(n)                 # must be a prime number
    x = filter(n, x)         # now remove its multiples
</code></pre>

<p>This does not have much to do with the question, but on my machine using <code>Python 3.4.3</code> a stack overflow happens somewhere for <code>N&gt;7500</code>. Using <code>sieve.lua</code> with <code>Lua 5.2.3</code> the stack overflow happens already at <code>N&gt;530</code>.</p>

<p>Generator objects (which represent a suspended coroutine) can be passed around like any other object, and the next() built-in can be applied to it in any place, so coroutines in python are first-class. Please correct me if I am wrong.</p>

python asynchronous lua async-await coroutine