Guido van Rossum wrote:
PEP 310 forms the basis for a block construct that I _do_ like. The question then becomes whether or not generators can be used to write useful PEP 310 style block managers (I think they can, in a style very similar to that of the looping block construct from PEP 340).
I've read through your example, and I'm not clear why you think this is better. It's a much more complex API with less power. What's your use case? Why should 'block' be disallowed from looping? TOOWTDI or do you have something better?
I'm no longer clear on why I thought what I suggested would be better either. Can I use the 'it was late' excuse? :) Actually, the real reason is that I hadn't figured out what was really possible with PEP 340. The cases that I thought PEP 310 would handle better, I've since worked out how to do using the PEP 340 mechanism, and PEP 340 handles them _far_ more elegantly. With PEP 340, multi-stage constructs can be handled by using one generator as an argument to the block, and something else (such as a class or another generator) to maintain state between the blocks. The looping nature is a big win, because it lets execution of a contained block be prevented entirely. My favourite discovery is that PEP 340 can be used to write a switch statement like this: block switch(value) as sw: block sw.case(1): # Handle case 1 block sw.case(2): # Handle case 2 block sw.default(): # Handle default case Given the following definitions: class _switch(object): def __init__(self, switch_var): self.switch_var = switch_var self.run_default = True def case(self, case_value): self.run_default = False if self.switch_var == case_value: yield def default(self): if self.run_default: yield def switch(switch_var): yield _switch(switch_var) With the keyword-less syntax previously mentioned, such a 'custom structure' could look like: switch(value) as sw: sw.case(1): # Handle case 1 sw.case(2): # Handle case 2 sw.default(): # Handle default case (Actually doing a switch using blocks like this would be *insane* for performance reasons, but it is still rather cool that it is possible) With an appropriate utility block manager PEP 340 can also be used to abstract multi-stage operations. I haven't got a real use case for this as yet, but the potential is definitely there: def next_stage(itr): """Execute a single stage of a multi-stage block manager""" arg = None next_item = next(itr) while True: if next_item is StopIteration: raise StopIteration try: arg = yield next_item except: if not hasattr(itr, "__error__"): raise next_item = itr.__error__(sys.exc_info()[1]) else: next_item = next(itr, arg) def multi_stage(): """Code template accepting multiple suites""" # Pre stage 1 result_1 = yield # Post stage 1 yield StopIteration result_2 = 0 if result_1: # Pre stage 2 result_2 = yield # Post stage 2 yield StopIteration for i in range(result_2): # Pre stage 3 result_3 = yield # Post stage 3 yield StopIteration # Pre stage 4 result_4 = yield # Post stage 4 def use_multistage(): blk = multi_stage() block next_stage(blk): # Stage 1 continue val_1 block next_stage(blk): # Stage 2 continue val_2 block next_stage(blk): # Stage 3 continue val_3 block next_stage(blk): # Stage 4 continue val_4 Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.skystorm.net