PEP 340 has many ideas I like: - enhanced yield statements and yield expressions - enhanced continue and break - generator finalisation - 'next' builtin and associated __next__() slot - changes to 'for' loop
One restriction I don't like is the limitation to ContinueIteration and StopIteration as arguments to next(). The proposed semantics and conventions for ContinueIteration and StopIteration are fine, but I would like to be able to pass _any_ exception in to the generator, allowing the generator to decide if a given exception justifies halting the iteration.
The _major_ part I don't like is that the block statement's semantics are too similar to those of a 'for' loop. I would like to see a new construct that can do things a for loop can't do, and which can be used in _conjunction_ with a for loop, to provide greater power than either construct on their own.
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).
Block statement syntax from PEP 340:
block EXPR1 [as VAR1]: BLOCK1
Proposed semantics (based on PEP 310, with some ideas stolen from PEP 340):
blk_mgr = EXPR1 VAR1 = blk_mgr.__enter__() try: try: BLOCK1 except Exception, exc: blk_mgr.__except__(exc) else: blk_mgr.__else__() finally: blk_mgr.__exit__()
'blk_mgr' is a hidden variable (as per PEP 340).
Note that nothing special happens to 'break', 'return' or 'continue' statements with this proposal.
Generator methods to support the block manager protocol used by the block statement:
def __enter__(self): try: return next(self) except StopIteration: raise RuntimeError("Generator exhausted before block statement")
def __except__(self, exc): try: next(self, exc) except StopIteration: pass
def __no_except__(self): try: next(self) except StopIteration: pass
def __exit__(self): pass
Writing simple block managers with this proposal (these should be identical to the equivalent PEP 340 block managers):
def opening(name): opened = open(name) try: yield opened finally: opened.close()
def logging(logger, name): logger.enter_scope(name) try: try: yield except Exception, exc: logger.log_exception(exc) finally: logger.exit_scope()
def transacting(ts): ts.begin() try: yield except: ts.abort() else: ts.commit()
Using simple block managers with this proposal (again, identical to PEP 340):
block opening(name) as f: pass
block logging(logger, name): pass
block transacting(ts): pass
Obviously, the more interesting block managers are those like auto_retry (which is a loop, and hence an excellent match for PEP 340), and using a single generator in multiple block statements (which PEP 340 doesn't allow at all). I'll try to get to those tomorrow (and if I can't find any good use cases for the latter trick, then this idea can be summarily discarded in favour of PEP 340).
Cheers, Nick.
-- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.skystorm.net _______________________________________________ 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