Calvin Spealman wrote:
A "sane stack trace" only makes sense if we assume that tasks "call" each other in the same kind of call tree that synchronous code flows in, and I don't think that is necessarily the case.
No, but often it *is* the case, and in those cases we would like to get a traceback that correctly reflects the chain of calls.
There are cases when one task might want to end before tasks it as "called" are complete, and if we use yield-from this is *impossible* but it is very useful.
That depends on what you mean by "use yield-from". It's true that yield-from *on its own* can't achieve the effect of spawning concurrent subtasks; other mechanisms will need to be brought to bear at some point.
But there's no reason a solution involving those other mechanisms can't be encapsulated in a library function that you invoke using yield-from. I've posted a couple of examples of how a par() function which does that might be written.
yield-from semantics won't allow a called task to continue, if needed, after the calling task itself has completed.
You seem to be imagining that more is being claimed about the abilities of yield-from than is actually being claimed. Yield-from is just a procedure call; the important thing is what the called procedure does.
One of the things it can do is invoke a scheduler primitive that spawns an independent task. In my example scheduler, this is spelled scheduler.schedule(task). This is not a yield-from call, it's just an ordinary call. It adds the given generator to the list of ready tasks, so that it will get run when its chance comes around. Meanwhile, the calling task carries on.