On Wed, Oct 17, 2012 at 3:16 AM, Greg Ewing
Guido van Rossum wrote:
On Tue, Oct 16, 2012 at 12:20 AM, Greg Ewing
wrote: it blurs the distinction between invoking a subtask synchronously and waiting for the result of a previously spawned independent task.
Are you sure you really want to distinguish between those though?
I think I do. Partly because I feel that not doing so would make code harder to reason about. Async stuff is difficult enough as it is without hiding the boundaries between one thread of control and another.
There are technical reasons as well. If you use 'yield from' to wait for completion of an independent task, then it would seem like you should be able to do this:
t1 = task1() t2 = task2() spawn(t1) spawn(t2) r1 = yield from t1 r2 = yield from t2
But that can't work -- the object that you wait on has to be different from the generator instance passed to spawn(). The reason is that if the task finishes before anyone waits on it, the return value needs to be stored somewhere.
Having spawn() return an object that deliberately does *not* have the interface of a generator, and having to explicitly wait for it, makes it much less likely that anyone will make that kind of mistake. If you wrote
t1 = task1() t2 = task2() spawn(t1) spawn(t2) r1 = yield from t1.wait() r2 = yield from t2.wait()
you would quickly get an exception, because generators don't have a wait() method.
Ack. I get it. It's like the difference between calling a function vs. running it in an OS thread. -- --Guido van Rossum (python.org/~guido)