It's pretty obvious what programmer wants to achieve. But with generators you can't call "yield" from deeper-level function - generators are one-level-deep. The only way to compose is to 'yield' a new (deeper) generator. At this point, the caller of hour_sound() needs to understand what to do if the callee returns a generator, instead of 'null' or a valid value. And it needs to run this "deep" generator before doing 'send' on the hour_sound again.
This is just the beginning of the mess. Errors get very hard to track as tracebacks get completely unreadable. It's not easy to decide what to do when one of the nested generators throws an exception.
All this magic is heavily based on the way python exceptions are integrated with generators, for example one can try to catch "StopIteration" to do a cleanup within generator. I doubt this is possible in javascript as the exceptions mechanism is much less mature.
Edit: Don't get me wrong - I love generators! But one-level-deep generators are not coroutines with stack that can be "blocked" from any deeper function.
If Javascript did the same thing, you would write yield from second_sound(); in hour_sound, and then you could run hour_sound as a generator and it would Just Work.
"inlineCallbacks" is 3 lines long. "_inlineCallbacks" is around 50 lines long :)
Let's not get into discussion if tornado is better or not than twisted. Both have similar mechanism to flatten generators and both mechanisms are much more complex than one could expect. Also, both of them heavily depend on python exception handling.
BTW, this is brilliant:
# This function is complicated by the need to prevent unbounded recursion
# arising from repeatedly yielding immediately ready deferreds. This while
# loop and the waiting variable solve that by manually unfolding the
# recursion.
Most importantly - generators don't compose.
(I'm talking about python-style generators, the type of generators javascript adapted.)
To give you an idea of what I mean:
It's pretty obvious what programmer wants to achieve. But with generators you can't call "yield" from deeper-level function - generators are one-level-deep. The only way to compose is to 'yield' a new (deeper) generator. At this point, the caller of hour_sound() needs to understand what to do if the callee returns a generator, instead of 'null' or a valid value. And it needs to run this "deep" generator before doing 'send' on the hour_sound again.This is just the beginning of the mess. Errors get very hard to track as tracebacks get completely unreadable. It's not easy to decide what to do when one of the nested generators throws an exception.
Python frameworks went through this long time ago, see here (look especially for the "yield" keyword): http://www.tornadoweb.org/documentation/gen.html
Here's a bit of the underlying logic of this "simple" "coroutine-programming-syle" layer of tornadoweb: http://www.tornadoweb.org/documentation/_modules/tornado/gen...
And here's more! https://github.com/facebook/tornado/blob/master/tornado/gen....
All this magic is heavily based on the way python exceptions are integrated with generators, for example one can try to catch "StopIteration" to do a cleanup within generator. I doubt this is possible in javascript as the exceptions mechanism is much less mature.
Edit: Don't get me wrong - I love generators! But one-level-deep generators are not coroutines with stack that can be "blocked" from any deeper function.