On 8/30/05, Stefano Masini <stefano@pragma2000.com> wrote:
The problem with generators and enhanced generators, as I've been discussing with a few people at Europython, is that they allow you to jump back and forth between two stack *frames*. Whereas greenlets support jumping among *full* stacks. This means that from within a @deferredGreenlet'ed function you can make calls to other functions that call blockOn, while from a @deferredGenerator'ed function you can't call a method that in turn calls waitForDeferred.
While this may seems quite a subtle difference, I think it is not if you look at it from the perspective of code readability -- let alone the 3 liner horrible hack that waitForDeferred forces you to, at least until PEP 342, as we all know.
The effect that being able to call things that do context switches without explicitly marking them as doing so is much farther reaching than code readability. I consider it something of a feature that deferredGenerator forces you to know when context switches will happen at every level, and when I wrote gthreadless I was not intending it to be used in a way that didn't require that same knowledge at every level. And I don't think that this extra knowledge along the line isn't detracting at all to readability, but instead helping it. As I said in another thread, I'm really looking forward to PEP 342 and I'm looking forward to obsoleting all of these other deferred + cooperative multitasking things I've written (threadless, gthreadless, and old-school-defgen) with newschool-PEP342-defgen. And, just for onlookers, I'd like to point out that the code example below is not showing the difference between non-explicit-greenlets and explicit-defgen, but instead showing the difference between explicit-greenlets and plain ond deferreds, which most of us in the know about the various deferred+cooperative multitasking integration modules already understand. No one as yet has shown an example showing where implicit context switching is a good thing. ...
Here is an example that makes justice to this approach. It involves Perspective Broker. Think of writing a web frontend to an application on the backend that exports functionality through pb. (the code may not work, I'm just making it up now without testing it) (I hope everybody is familiar with nevow.stan. If not, take a look at it. It's worth.)
@deferredGreenlet def renderPage(self): dataList = [ blockOn(self.backend.callRemote('getDataFromId', elementId)) for elementId in self.idList] return T.html[ T.body [ 'The result:', T.br, [ (txt, T.br) for txt in dataList ] ] ]
Without gthreadless:
def renderPage(self): dataList = [] def fetchDataRemotely(elementList): def cbFetch(elementData): dataList.append(elementData) if len(elementList) > 0: return fetchDataRemotely(elementList[1:]) return self.backend.callRemote('getDataFromId', elementId).addCallback(cbFetch) def cb(crap): return T.html[ T.body [ 'The result:', T.br, [ (txt, T.br) for txt in dataList ] ] ] return fetchDataRemotely(self.idList).addCallback(cb)
-- Twisted | Christopher Armstrong: International Man of Twistery Radix | -- http://radix.twistedmatrix.com | Release Manager, Twisted Project \\\V/// | -- http://twistedmatrix.com |o O| | w----v----w-+