Monocle seems nice enough, but the reliance on python's yield statement makes it difficult to cleanly decompose your logic into functions. You can do it, but you have to wrap each function call in a loop which re-yields each of the values from the function. That seems a bit icky.
It'll get a bit nicer with the yield from statement described in PEP 380, but it still means you have to have to prefix the function call - you can't just call it normally and have it do the right thing.
What I really worry about though is that Python - at least for web development - is becoming like Java, with frameworks to abstract over frameworks...
I'm not sure I understand your concern here. How does monocle make decomposing logic into functions difficult?
The "yield" keyword is an indicator of where control is returned back up to the event loop and other things can happen. We like that in monocle, because we view it as dangerous; in thread-and-lock terms, it's sort of like "unlock everything".
Eventlet (http://eventlet.net/) is an example of a similar framework that decided not to require "yield" at these points.
Let me start by saying that I actually think Monocle is nice work given the language mechanisms that Python provides and this is intended as constructive criticism.
What I meant by "makes it hard" is that it creates two different calling conventions for functions and you need to know how a function is implemented to determine which one to use. Also, if the implementation of a function changes you may need to find and change all the call sites of the function. These are not insurmountable problems by any means, but they are extra potential sources of error in a program.
I'm not familiar with Eventlet, but FWIW the Cocoon framework (http://cocoon.apache.org/) had a quite nice take on this model back in the day.
Right. You have to be very careful to always yield to another function that uses yield. It can become very hairy with deep call chains.
The limitation is that Python has to be statically prove that a function is really a generator for yield to work and they do this by forcing there to be a yield in the actual function.
I'd worked my way through all the problems having to do with simulating a generator-based "stack" and it was not pretty--exception handling in particular with these "fake stacks" was hard to make behave the usual pythonic way.
I wasn't eager to give up on a generators, but I had to eventually concede that the practical quality of the project was more important than the founding idea.
Everything has been faster, easier to program, and more stable since giving up on generators and moving to the greenlet library. At bump, we just launched version 2.0 of our app, running our backends 100% on diesel2/greenlets:
Their Deferred type looks like it's not thread-safe or able to handle reentrant invocations, which seems like it would limit the usefulness of this framework in the real world, since many asynchronous APIs require you to be able to handle being invoked from multiple threads.
Useful stuff, everyone should do it.
In fact, I just did the same thing with an event-driven GUI application in Ruby.
I'm wondering, it says it's designed to be portable between frameworks, how much is actually framework-specific? Is there a useful library in there that's completely agnostic to the surrounding event loop construction?
There's a JavaScript library called async.js (http://github.com/eligrey/async.js) that does that exact same thing (pseudo-asynchronosity using the yield statement in decorated functions).
It'll get a bit nicer with the yield from statement described in PEP 380, but it still means you have to have to prefix the function call - you can't just call it normally and have it do the right thing.
What I really worry about though is that Python - at least for web development - is becoming like Java, with frameworks to abstract over frameworks...