dabeaz / curio

Good Curio!
Other
4.02k stars 241 forks source link

how to avoid proliferation of async functions? #192

Closed goldcode closed 7 years ago

goldcode commented 7 years ago

Oftentimes, i come across the situation where i have a devised a coroutine function solely existing for the purpose of running a list of coroutines serially when used in a parallel context (see example for clarity).

This extra serial_coro is unnecessary function pollution for me. I haven't used python lambdas, but they don't seem c++-like to me.

Is there any language or library feature which would enable me to get rid of this extra (see serial_coro below) function?

in addition to less functions, it would then be possible to schedule a 'list of serialized coroutines' to be run in parallel with other coroutines in a dynamic manner.

If this is old hat, please point me an to an example, if existing.

e.g.

async def serial_coro():
    await a()
    await b()
    await c()

async def x():
    pass

async def y():
    pass

async def some_big_function():

    # ideally i would like to use something like
    # await curio.spawn_serial(a(), b(), c()) instead of await curio.spawn(serial_coro())

    results = [await task.join() for task in (
            await curio.spawn(serial_coro()),
            await curio.spawn(x()),
            await curio.spawn(y())]
dabeaz commented 7 years ago

async functions are weird. You could certainly write things like this:

async def sequence(*args):
    for coro in args:
         await coro

async def some_big_function():
       await sequence(
               a(),
               b(),
               c()
       )

In terms of curio, the closest thing might be the gather() and wait() functions--although those are more for concurrent execution of tasks.

goldcode commented 7 years ago

nice! That should do the trick i think.

The use case here: i have to serialize a set of hardware components movements(coros here), to avoid collisions with one another. These serialized movements can however be executed in parallel with other movements from other unrelated hardware components.

so in my case it would be so:

results = [await task.join() for task in (
            await curio.spawn(sequence(a(), b(), c())),
            await curio.spawn(x()),
            await curio.spawn(y())]
dabeaz commented 7 years ago

For the moment, I'm somewhat hesitant to add exotic functionality to Curio to wrap coroutine execution in different patterns like this. However, I'd encourage you to play with this sort of thing and report back. This application sounds interesting.