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 at gmail.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.skystorm.net
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4