Guido van Rossum <[EMAIL PROTECTED]> writes: > [Greg Ewing] >> Elegant as the idea behind PEP 340 is, I can't shake >> the feeling that it's an abuse of generators. It seems >> to go to a lot of trouble and complication so you >> can write a generator and pretend it's a function >> taking a block argument. > > Maybe. You're not the first one saying this and I'm not saying "no" > outright, but I'd like to defend the PEP.
This is kind of my point too; I'm not saying that I really prefer the thunk solution, just that I want to see it mentioned. I think the making-generators-more-sexy thing is nice, but I'm think that's almost orthogonal. [...] > Even without a block-statement, these two changes make yield look a > lot like invoking a thunk -- but it's more efficient, since calling > yield doesn't create a frame. > > The main advantage of thunks that I can see is that you can save the > thunk for later, I also find them somewhat easier to understand. > like a callback for a button widget (the thunk then becomes a > closure). You can't use a yield-based block for that (except in > Ruby, which uses yield syntax with a thunk-based implementation). > But I have to say that I almost see this as an advantage: I think > I'd be slightly uncomfortable seeing a block and not knowing whether > it will be executed in the normal control flow or later. Defining an > explicit nested function for that purpose doesn't have this problem > for me, because I already know that the 'def' keyword means its body > is executed later. > > The other problem with thunks is that once we think of them as the > anonymous functions they are, we're pretty much forced to say that a > return statement in a thunk returns from the thunk rather than from > the containing function. Doing it any other way would cause major > weirdness when the thunk were to survive its containing function as a > closure (perhaps continuations would help, but I'm not about to go > there :-). I'm not so sure about this. Did you read this mail: http://mail.python.org/pipermail/python-dev/2005-April/052970.html ? In this proposal, you have to go to some effort to make the thunk survive the block, and I think if weirdness results, that's the programmer's problem. > But then an IMO important use case for the resource cleanup template > pattern is lost. I routinely write code like this: > > def findSomething(self, key, default=None): > self.lock.acquire() > try: > for item in self.elements: > if item.matches(key): > return item > return default > finally: > self.lock.release() > > and I'd be bummed if I couldn't write this as > > def findSomething(self, key, default=None): > block synchronized(self.lock): > for item in self.elements: > if item.matches(key): > return item > return default If you can't write it this way, the thunk proposal is dead. >> I'd like to reconsider a thunk implementation. It >> would be a lot simpler, doing just what is required >> without any jiggery pokery with exceptions and >> break/continue/return statements. It would be easy >> to explain what it does and why it's useful. > > I don't know. In order to obtain the required local variable sharing > between the thunk and the containing function I believe that every > local variable used or set in the thunk would have to become a 'cell' > (our mechanism for sharing variables between nested scopes). Yes. > Cells slow down access somewhat compared to regular local variables. So make them faster. I'm not sure I think this is a good argument. You could also do some analysis and treat variables that are only accessed or written in the block as normal locals. This all makes a block-created thunk somewhat different from an anonymous function, to be sure. But the creating syntax is different, so I don't know if I care (hell, the invoking syntax could be made different too, but I really don't think that's a good idea). > Perhaps not entirely coincidentally, the last example above > (findSomething() rewritten to avoid a return inside the block) shows > that, unlike for regular nested functions, we'll want variables > *assigned to* by the thunk also to be shared with the containing > function, even if they are not assigned to outside the thunk. I swear > I didn't create the example for this purpose -- it just happened. Oh, absolutely. >> On the other hand, a thunk implementation has the >> potential to easily handle multiple block arguments, if >> a suitable syntax could ever be devised. It's hard >> to see how that could be done in a general way with >> the generator implementation. > > Right, but the use cases for multiple blocks seem elusive. If you > really want to have multiple blocks with yield, I suppose we could use > "yield/n" to yield to the n'th block argument, or perhaps yield>>n. > :-) Hmm, it's nearly *May* 1... :) Cheers, mwh -- I'm a keen cyclist and I stop at red lights. Those who don't need hitting with a great big slapping machine. -- Colin Davidson, cam.misc _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com