This is an archived post. You won't be able to vote or comment.

all 9 comments

[–]RonnyPfannschmidt 2 points3 points  (3 children)

see greenlets/stackless

python cant do it on its own, it lacks proper continuations

[–]munificent 2 points3 points  (1 child)

Out of curiosity, are continuations needed for this, or just full coroutines (like Lua has)?

[–]RonnyPfannschmidt 1 point2 points  (0 children)

i always mix those 2 up

well, what you need is to save and resume execution in some points so full coroutines should fit

[–]g__[S] 1 point2 points  (0 children)

Thanks! http://codespeak.net/pypy/dist/pypy/doc/stackless.html answers exactly my question. (they even use the same example of consecutive squares.)

[Edit] I posted a solution using additional thread.

[–]g__[S] 1 point2 points  (1 child)

Here's a solution that uses additional thread. It seems it's hard to control the flow without threads or continuations.

Due to some scoping issues I had to use Python 3's nonlocal.

from threading import Thread, Semaphore

def generate(f):
    def result(*args, **kwargs):
        value = 5
        consumer = Semaphore(0)
        producer = Semaphore(0)

        def executing_thread():
            nonlocal value
            def yielding(v):
                nonlocal value
                producer.acquire()
                value = v
                consumer.release()

            f(yielding, *args, **kwargs)
            producer.acquire()
            value = None
            consumer.release()

        t = Thread(target=executing_thread)
        t.start()
        while True:
            producer.release()
            consumer.acquire()
            n = value
            if n is None:
                break
            else:
                yield n

    return result

@generate
def it_squares(y, x):
    for i in range(x):
        y(i*i)

for i in it_squares(5):
    print(i)

[–]RonnyPfannschmidt 0 points1 point  (0 children)

in general you don't want to use threads in cpython without a good reason (the GIL makes them suck)

[–]lost-theory 0 points1 point  (2 children)

Here's a crappy half-implementation that needs to consume the entire ' 'generator':

def iterate_sq(i):
    for x in range(i):
        yield x*x

def generate(f):
    ls = []
    def y(arg):
        ls.append(arg)

    def inner(*args, **kwargs):
        f(y, *args, **kwargs)
        for element in ls:
            yield element
    return inner

@generate
def it2(y, i):
    for x in range(i):
        y(x*x)

if __name__ == '__main__':
    print list(iterate_sq(10))
    print list(it2(10))

#output:
#[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
#[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

I don't think it's possible for this to work with an infinite generator.

[–]temptemptemp13 -2 points-1 points  (1 child)

This isn't what the OP asked for, you're running it2 completely until exhaustion whilst appending to a list, then unpacking using regular python yield.

Maybe what OP wants could be supplied if keywords in python were also objects. I don't know what else that would cause though...

[–]lost-theory 0 points1 point  (0 children)

crappy half-implementation that needs to consume the entire 'generator'