Re: [Python-Dev] PEP 340: Breaking out.
On 5/5/05, Steven Bethard [EMAIL PROTECTED] wrote: On 5/5/05, Paul Moore [EMAIL PROTECTED] wrote: And does your proposal allow for continue EXPR as supported by PEP 340? I can't see that it could, given that your proposal treats block statements as not being loops. Read PEP 340 again -- the continue EXPR syntax is orthogonal to the discussion -- PEP 340 adds it for *all* for loops, so for loops with the non-looping block statements would also be able to use it. I know this. But we're talking here about Nick's new proposal for a non-looping block. All I am saying is that the new proposal needs to include this orthogonal feature. If it's a modification to PEP 340, that will come naturally. If it's a modification to PEP 310, it won't. A new PEP needs to include it. I am very much against picking bits out of a number of PEPs - that was implicit in my earlier post - sorry, I should have made it explicit. Specifically, PEP 340 should be accepted (possibly with modifications) as a whole, or rejected outright - no rejected, but can we have continue EXPR in any case, as it's orthogonal status exists... The looping behaviour is a (fairly nasty) wart, but I'm not sure I would insist on removing it at the cost of damaging other features I like. I don't think it damages any features. Are there features you still think the non-looping proposal removes? (I'm not counting orthogonal feautres like continue EXPR which could easily be added as an entirely separate PEP.) I *am* specifically referring to these orthogonal features. Removal of looping by modification of PEP 340 will do no such damage, I agree - but removal by accepting an updated PEP 310, or a new PEP, *will* (unless the entirely separate PEP you mention is written and accepted along with the non-looping PEP - and I don't think that will happen). Thanks for making me clarify what I meant. I left a little too much implicit in my previous post. Paul. ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
On 5/6/05, Greg Ewing [EMAIL PROTECTED] wrote: Seems to me it should be up to the block iterator whether a break statement gets caught or propagated, since it's up to the block iterator whether the construct behaves like a loop or not. This could be achieved by having a separate exception for breaks, as originally proposed. If the iterator propagates the Break exception back out, the block statement should break any enclosing loop. If the iterator wants to behave like a loop, it can catch the Break exception and raise StopIteration instead. Yes, that's exactly what I was trying to say! I don't know if it's achievable in practice, but the fact that it was in the original proposal (something I'd forgotten, if indeed I ever realised) makes it seem more likely to me. Paul. ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
Guido van Rossum wrote: Maybe generators are not the way to go, but could be supported natively by providing a __block__ function, very similarly to sequences providing an __iter__ function for for-loops? Sorry, I have no idea what you are proposing here. I was suggesting that the feature could be a PEP310-like object and that a __block__ function (or whatever) of the generator could return such an object. But at this point, Nick's proposition is what I prefer. I find the use of generators very elegant, but I'm still unconvinced it is a good idea to use them to implement an acquire/release pattern. Even if another continuation mechanism would be used (like Steven's idea), it would still be a lot of concepts used to implement acquire/release. Regards, Nicolas ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
On Thu, 5 May 2005, Delaney, Timothy C (Timothy) wrote: Aahz wrote: My standard workaround is using exceptions, but I'm not sure how that interacts with a block: try: for name in filenames: with opened(name) as f: if f.read(2) == 0xFEB0: raise Found except Found: pass For any sane block iterator, it will work as expected. However, an evil block iterator could suppress the `Found` exception. I was thinking about more use cases for the block statement, and one of the ideas was an exception-logging block: def logged_exceptions(file): try: yield except Exception, value: file.write(repr(value) + '\n') block logged_exceptions(file): do stuff do stuff do stuff ...but then i wasn't sure whether this was supposed to be possible in the proposed scheme. Currently, generators do not catch exceptions raised in the code that they yield values to, because the target of the yield is in a higher stack frame. This makes sense from a language design perspective, since there is no try...finally construct lexically wrapping the thing that raises the exception. In current Python, for example, this says 'caught outside generator': def spam_generator(): try: yield 'spam' except ValueError, value: print 'caught inside generator' try: g = spam_generator() i = g.next() raise ValueError(5) except ValueError, value: print 'caught outside generator' But now i'm confused. Tim's words above seem to suggest that the interior generator could actually catch exceptions raised outside, by whatever is on the other end of the yield. So, could a block statement really catch that exception inside? I think it might be too confusing if it were possible. -- ?!ng ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
Steven Bethard wrote: Makes me wonder if we shouldn't just return to the __enter__() and __exit__() names of PEP 310[1] where for a generator __enter__() is just an alias for next(). We could even require Phillip J. Eby's blockgenerator decorator to rename next() to __enter__(), and add the appropriate __exit__() method. You must be reading my mind or something. . . Unless there is something in today's 80-odd messages to make it redundant, look for a post entitled something like Minimalist PEP 340 (aka PEP 310 redux) 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
Re: [Python-Dev] PEP 340: Breaking out.
Alex Martelli wrote: Looking for a file with a certain magicnumber in its 1st two bytes...? for name in filenames: opening(name) as f: if f.read(2) == 0xFEB0: break This does seem to make real-life sense to me... Also consider the vast semantic differences between: locking(lock): for item in items: if can_handle(item): break for item in items: locking(lock): if can_handle(item): break Instead of simply acquiring and releasing the lock on each iteration as one might expect, moving to the latter version *also* causes every item to be checked, instead of only items up to the first one that can be handled. The break magically becomes meaningless. How does this even come close to executable pseudocode? I also think another factor is that currently, instead of doing try/finally's in loops, there is a tendency to push the try/finally into a function, then call that function inside the loop. The introduction of block statements means that a number of those inner functions are likely to be handled as block statements instead - with the above highly confusing result. 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
Re: [Python-Dev] PEP 340: Breaking out.
Ronald Oussoren wrote: What's bothering me about the proposed semantics is that block statement behaves like a loop while most use cases do no looping whatsoever. Furthermore the it doesn't feel like loop either. In all three examples on this page I'd assume that the break would break out of the for loop. I'm bothered the same way. IMHO control constructs should be very clear. No implicit looping, conditionals etc. Especially since the main reason to have this whole discussion is about resource management. The main pattern of use I have in mind is: resource = grab/allocate/open/whatever(...) try: do something possibly with the resource except ...: ... finally: ... resource.release/deallocate/close/whatever() This is linear. No looping whatsoever. And easily translated to a simple language construct and a protocol: class resource(object): def __init__(self,...): # store resource parameters def __acquire__(self): # whatever it takes to grab the resource def __release__(self): # free the resource res = resource(...) acquire res: do something possibly with the resource except ...: ... finally: ... The resource is automagically released at the end of the 'acquire' block (keyword up for other proposals :-) An alternative syntax could also be allowed: acquire resource(...) as res: ...etc... Then 'res' would be undefined after the 'acquire' block. --eric ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
On 5/5/05, Nick Coghlan [EMAIL PROTECTED] wrote: Steven Bethard wrote: Makes me wonder if we shouldn't just return to the __enter__() and __exit__() names of PEP 310[1] where for a generator __enter__() is just an alias for next(). We could even require Phillip J. Eby's blockgenerator decorator to rename next() to __enter__(), and add the appropriate __exit__() method. You must be reading my mind or something. . . Unless there is something in today's 80-odd messages to make it redundant, look for a post entitled something like Minimalist PEP 340 (aka PEP 310 redux) Yeah, I should have linked to that discussion [1]. I wonder if it would be possible to update PEP 310 with your ideas, or perhaps start a new PEP? I'd like to see a competitor for PEP 340 that addresses some of the issues that came up, e.g. that the block-statement doesn't look like a loop, so break and continue might look like they break out of an enclosing loop. It might also be a good place to mirror Guido's PEP 340 examples with PEP 310-style examples -- I know the first attempts at writing some of them weren't as clean as the later attempts, so it would be nice to have somewhere to look for the current version of everything. STeVe [1]http://mail.python.org/pipermail/python-dev/2005-April/053039.html -- You can wordify anything if you just verb it. --- Bucky Katt, Get Fuzzy ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
Ka-Ping Yee [EMAIL PROTECTED] wrote: On Thu, 5 May 2005, Josiah Carlson wrote: Ka-Ping Yee [EMAIL PROTECTED] wrote: continue with 2 There is something about action which level that I just don't like. Just to clarify: if by level you mean nesting level, did it appear that the 2 in my example was a count of block levels? I didn't mean it that way -- the 2 is a value passed in to the generator that appears as the value of the yield expression, as in PEP 340. I remember reading that, but I seem to have forgotten it when I was composing my reply. Thankfully, sleeping on it has helped me discover what I really don't like. With the 'passing value' semantic, the action [ which ] [ value ] is only useful for the deepest loop of a particular type. Take for example... for ...: for ...: for ...: break/continue [for] That break or continue can only affect that last for loop. It doesn't make any easier the use of nested fors, nested whiles, or even nested blocks. It only really helps you if you mix and match all possible looping constructs, and even then, only gives the granularity of the most recent block of a particular type. In that sense, I think it is a nonstarter, because it doesn't really add functionality in common uses of for and while statements. If one allowed action [which] [value] , [level], then one could jump to arbitrary loops. Now, I'm not condoning this, and I don't even like it. Sure, it allows breaking or continuing to any for, while, or block statement in the current scope, but the level argument is as equivalently ambiguous as package-relative imports using a leading integer (http://python.org/peps/pep-0328.html). Now, one can remove ambiguity if we were able to 'label' while loops and for loops producing action [ label ] , [ value ], but at that point we are getting into the discussion of a loop-aware goto with loop/block cleanup, and a syntax for labeling loops. Ick. - Josiah ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
On 5/5/05, Nick Coghlan [EMAIL PROTECTED] wrote: Well, Michael Hudson and Paul Moore are the current authors of PEP 310, so updating it with any of my ideas would be their call. I'm willing to consider an update - I don't know Michael's view. I currently find myself in the odd situation of defending PEP 340 against PEP 310, though. I'll try to rationalise why below... Either way, my latest and greatest version of the non-looping block statement semantics can be found here: http://mail.python.org/pipermail/python-dev/2005-May/053400.html I can't reconcile this description with that of PEP 310. The basic reason is that the styles are very different, compounded by the fact that I don't have the time to give this the analysis it needs. My instinct is that if your proposal can't be described in terms of a relatively small change to one of PEP 310 or 340, then my view is it's a 3rd proposal in its own right, and I'd rather not open things up that much again. Some key advantages of that proposal are: 1. It's not a loop, so nesting it inside another loop 'just works' This, to me, is the main issue 2. Manual protocol implementations are _significantly_ easier to write Hmm, I've not tried so I'll have to take your word for this. But I don't imagine writing manual implementations much - one of the key features I like about Guido's proposal is that generators can be used, and the implementation is a clear template, with yield acting as a put the block here marker (yes, I know that's an oversimplification!). 3. try/finally can be done with generators _without_ changing generators How is this an advantage? PEP 340 allows try/finally inside generators - if that counts as changing generators I don't see why I care (as a user). But I think I'm missing something here - I never really followed (or cared about) the generator finalisation issues. 4. try/except/else can be done with generators if they provide an __exit__ method that raises the exception at the point of the last yield As above - I'm not sure I follow. 5. Clearly distinct construct, no potential for confusion with for loops OK, but that's really just saying not a loop again. 6. Generators must be clearly marked as creating a user defined statement (although this could be changed by giving them an __enter__ method and an __exit__ method) I still don't see a compelling argument that this is a good thing. I'm neutral on this. The one downside relative to PEP 340 is that looping constructs like auto_retry are slightly harder to write, albeit not hugely so (once you remember that an iterable can be a class instead of a generator!). Are you *sure* that's the only downside? Early on in the PEP 340 discussion, generator finalisation was a point of discussion. I didn't follow the details, but I believe that one of the points of PEP 340 was that it addressed the issues (to some extent - I really don't know if the generator finalisation PEPs are rendered obsolete by PEP 340, are completely orthogonal, or somewhere in between). I have no feel for whether your proposal covers these issues in the same way as PEP 340 does. And does your proposal allow for continue EXPR as supported by PEP 340? I can't see that it could, given that your proposal treats block statements as not being loops. Having just noticed this, I start to feel less convinced that block-as-loop is ultimately wrong. There aren't any examples of continue EXPR included in PEP 340 yet - a fact that Guido has acknowledged in item 9 of the examples section. Maybe Philip or one of the other coroutine fans would like to contribute some examples? On the usage front, I find the 'loop over an iterator returning user defined statements' does a much better job of making the iteration clear, so I'd be inclined to count that as an advantage of a PEP 310 style approach. I can accept that. It's a minor style point either way. The wording of it - as returning user defined statements makes me nervous though, as it implies that user-defined statements are first class objects - which feels wrong. Anyway, I've already been spending more time on this than I should (sleep is optional, right?), so I won't be prettying it up into PEP format any time soon. I have no objection to someone else rolling some of the ideas into a PEP, though :) I think *someone* has to care enough (and have the time) to make a proper PEP out of this. If it's a minor change to either of PEP 310 or PEP 340, that's OK. If it's too big for that, it needs to be fleshed out as a full competing PEP in its own right. Oh - and the promised rationalisation of my preference for PEP 340 over PEP 310. Things I like about PEP 340: - Using generators as templates with yield as a put the block here placeholder. It may be that a modification of PEP 310 can provide this, but that PEP doesn't exist yet (sorry!) - The coroutine style continue EXPR feature (I still need motivating examples but as a
Re: [Python-Dev] PEP 340: Breaking out.
On 5/5/05, Paul Moore [EMAIL PROTECTED] wrote: And does your proposal allow for continue EXPR as supported by PEP 340? I can't see that it could, given that your proposal treats block statements as not being loops. Read PEP 340 again -- the continue EXPR syntax is orthogonal to the discussion -- PEP 340 adds it for *all* for loops, so for loops with the non-looping block statements would also be able to use it. The looping behaviour is a (fairly nasty) wart, but I'm not sure I would insist on removing it at the cost of damaging other features I like. I don't think it damages any features. Are there features you still think the non-looping proposal removes? (I'm not counting orthogonal feautres like continue EXPR which could easily be added as an entirely separate PEP.) STeVe -- You can wordify anything if you just verb it. --- Bucky Katt, Get Fuzzy ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
Seems to me it should be up to the block iterator whether a break statement gets caught or propagated, since it's up to the block iterator whether the construct behaves like a loop or not. This could be achieved by having a separate exception for breaks, as originally proposed. If the iterator propagates the Break exception back out, the block statement should break any enclosing loop. If the iterator wants to behave like a loop, it can catch the Break exception and raise StopIteration instead. -- Greg Ewing, Computer Science Dept, +--+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | [EMAIL PROTECTED] +--+ ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
Simon Percivall wrote: And this is not confusing in what way? I don't think it's any less confusing than having a construct in the first place which can either be a loop or not. You need to know the semantics of the block iterator in order to know whether it's a loop. Once you know that, you know how break behaves (as long as the iterator is sanely designed). Making it depend means you constantly have to readjust your understanding of the statement based on the context. And this is _if_ you know how it behaves in the particular case. If you're trying to understand the source code, having break depend on something defined somewhere completely else seems like an obstacle to easy understanding. IMHO, of course. //Simon -- Greg Ewing, Computer Science Dept, +--+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | [EMAIL PROTECTED] +--+ ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
Delaney, Timothy C (Timothy) wrote: In this scenario (and I'm not saying I approve or disapprove) I think BreakIteration should inherit from StopIteration (thus retaining the existing PEP 340 semantics if uncaught):: Not sure I understand. The point of my suggestion was to *not* retain existing PEP 340 semantics if uncaught, i.e. break an enclosing loop rather than just terminate the block statement. -- Greg Ewing, Computer Science Dept, +--+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | [EMAIL PROTECTED] +--+ ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
Paul Moore wrote: Oh, and by the way - I prefer the keywordless form of the block statement (as used in my examples above). But it may exacerbate the issue with break unless we have a really strong name for these constructs may exacerbate? Something of an understatement, unfortunately. 'break' and 'continue' are going to be useless in most block statements, and in most of the cases where that is true, one would expect them to break out of a surrounding loop. Reconsidering the non-looping semantics I discussed way back at the start of this exercise, this is what using auto_retry would look like with a single-pass block statement: for attempt in auto_retry(3, IOError): attempt: # Do something! # Including break and continue to get on with the next attempt! (Now that's what I call a user defined statement - we're iterating over a list of them!) Anyway, auto_retry and the block statements it returns could be implemented as: def suppressing(exc=Exception, on_success=None): Suppresses the specified exception in the following block try: yield except exc: pass else: if on_success is not None: on_success() def just_do_it(): Simply executes the following block yield def auto_retry(times, exc=Exception): Generates the specified number of attempts class cb(): succeeded = False def __init__(self): cb.succeeded = True for i in xrange(times-1): yield suppressing(exc, cb) if cb.succeeded: break else: yield just_do_it() (Prettier than my last attempt at writing this, but still not very pretty. However, I'm willing to trade the need for that callback in the implementation of auto_retry to get non-surprising behaviour from break and continue, as the latter is visible to the majority of users, but the former is not) Note that the code above works, even *if* the block statement is a looping construct, making a mess out of TOOWTDI. Making it single pass also simplifies the semantics of the block statement (using VAR1 and EXPR1 from PEP 340): finalised = False block_itr = EXPR1 try: try: VAR1 = block_itr.next() except StopIteration: # Can still choose not to run the block at all finalised = True except: # There was an exception. Handle it or just reraise it. finalised = True exc = sys.exc_info() ext = getattr(block_itr, __exit__, None) if ext is not None: ext(*exc) # May re-raise *exc else: raise *exc # Well, the moral equivalent :-) finally: if not finalised: # The block finished cleanly, or exited via # break, return or continue. Clean up the iterator. ext = getattr(block_itr, __exit__, None) if ext is not None: try: ext(StopIteration) except StopIteration: pass With single-pass semantics, an iterator used in a block statement would have it's .next() method called exactly once, and it's __exit__ method called exactly once if the call to .next() does not raise StopIteration. And there's no need to mess with the meaning of break, return or continue - they behave as usual, affecting the surrounding scope rather than the block statement. The only new thing needed is an __exit__ method on generators (and the block syntax itself, of course). Looks like I've come full circle, and am back to arguing for semantics closer to those in PEP 310. But I have a better reason now :) Actually, maybe referring to them as block statements, but using no keyword, is perfectly acceptable. As I write, I'm finding it more and more natural. Same here. Especially if the semantics are tweaked so that it *is* a straightforward statement instead of a loop. 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
Re: [Python-Dev] PEP 340: Breaking out.
On May 4, 2005, at 01:57, Paul Moore wrote: tried to construct a plausible example, I couldn't find a case which made real-life sense. For example, with Nicolas' original example: for name in filenames: opening(name) as f: if condition: break I can't think of a reasonable condition which wouldn't involve reading the file - which either involves an inner loop (and we already can't break out of two loops, so the third one implied by the opening block makes things no worse), or needs the whole file reading (which can be Looking for a file with a certain magicnumber in its 1st two bytes...? for name in filenames: opening(name) as f: if f.read(2) == 0xFEB0: break This does seem to make real-life sense to me... Alex ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
On 5/4/05, Alex Martelli [EMAIL PROTECTED] wrote: On May 4, 2005, at 01:57, Paul Moore wrote: I can't think of a reasonable condition which wouldn't involve reading the file - which either involves an inner loop (and we already can't break out of two loops, so the third one implied by the opening block makes things no worse), or needs the whole file reading (which can be Looking for a file with a certain magicnumber in its 1st two bytes...? for name in filenames: opening(name) as f: if f.read(2) == 0xFEB0: break This does seem to make real-life sense to me... Yes, that'd do. I can't say I think it would be common, but it's a valid case. And the workaround is the usual messy flag variable: for name in filenames: found = False opening(name) as f: if f.read(2) == 0xFEB0: found = True if found: break Yuk. Paul. ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
On 5/4/05, Nick Coghlan [EMAIL PROTECTED] wrote: With single-pass semantics, an iterator used in a block statement would have it's .next() method called exactly once, and it's __exit__ method called exactly once if the call to .next() does not raise StopIteration. And there's no need to mess with the meaning of break, return or continue - they behave as usual, affecting the surrounding scope rather than the block statement. The only new thing needed is an __exit__ method on generators (and the block syntax itself, of course). Makes me wonder if we shouldn't just return to the __enter__() and __exit__() names of PEP 310[1] where for a generator __enter__() is just an alias for next(). We could even require Phillip J. Eby's blockgenerator decorator to rename next() to __enter__(), and add the appropriate __exit__() method. Something like: class blockgen(object): def __init__(self, gen): self.gen = gen def __enter__(self): self.gen.next() def __exit__(self): # cause finally blocks to be executed def blockgenerator(genfunc): def getblockgen(*args, **kwargs): return blockgen(genfunc(*args, **kwargs)) return getblockgen to be used like: @blockgenerator def locking(lock): lock.acquire() try: yield finally: lock.release() 'Course, it might be even nicer if try/finally around a yield could only be used with block generators... To get a syntax error, we'd have to replace the decorator with a new syntax, e.g. Tim Delaney's resource instead of def syntax or maybe using something like blockyield or resourceyield instead of yield (though these are probably too long)... Steve [1]http://www.python.org/peps/pep-0310.html -- You can wordify anything if you just verb it. --- Bucky Katt, Get Fuzzy ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
Paul Moore wrote: On 5/4/05, Alex Martelli [EMAIL PROTECTED] wrote: On May 4, 2005, at 01:57, Paul Moore wrote: I can't think of a reasonable condition which wouldn't involve reading the file - which either involves an inner loop (and we already can't break out of two loops, so the third one implied by the opening block makes things no worse), or needs the whole file reading (which can be Looking for a file with a certain magicnumber in its 1st two bytes...? for name in filenames: opening(name) as f: if f.read(2) == 0xFEB0: break This does seem to make real-life sense to me... Yes, that'd do. I can't say I think it would be common, but it's a valid case. And the workaround is the usual messy flag variable: for name in filenames: found = False opening(name) as f: if f.read(2) == 0xFEB0: found = True if found: break Is there anything we could do about this? Reinhold -- Mail address is perfectly valid! ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
Alex Martelli wrote: Looking for a file with a certain magicnumber in its 1st two bytes...? for name in filenames: opening(name) as f: if f.read(2) == 0xFEB0: break This does seem to make real-life sense to me... I'd like to suggest a small language enhancement that would fix this example. Allow the break and continue statements to use a keyword, either for or while, to state that the code should break out of both the block statement and the innermost for or while statement. The example above would change to: for name in filenames: opening(name) as f: if f.read(2) == 0xFEB0: break for This could be a separate PEP if necessary. When a break for is used in a block statement, it should raise a new kind of exception, BreakForLoop, and the block statement should propagate the exception. When used outside a block statement, break for can use existing Python byte code to jump directly to the next appropriate statement. Shane ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
On Wed, 4 May 2005, Shane Hathaway wrote: I'd like to suggest a small language enhancement that would fix this example. Allow the break and continue statements to use a keyword, either for or while, to state that the code should break out of both the block statement and the innermost for or while statement. The example above would change to: for name in filenames: opening(name) as f: if f.read(2) == 0xFEB0: break for This is very elegant. It works beautifully with break, though at first that natural analogs continue for, continue while appear to conflict with Guido's proposed extension to continue. But if we choose the keyword with to introduce an anonymous block, it comes out rather nicely: continue with 2 That's easier to read than continue 2, in my opinion. (If it's not too cute for you.) Anyway, i like the general idea of letting the programmer specify exactly which block to break/continue, instead of leaving it looking ambiguous. Explicit is better than implicit, right? -- ?!ng ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
Ka-Ping Yee wrote: On Wed, 4 May 2005, Shane Hathaway wrote: for name in filenames: opening(name) as f: if f.read(2) == 0xFEB0: break for This is very elegant. Thanks. It works beautifully with break, though at first that natural analogs continue for, continue while appear to conflict with Guido's proposed extension to continue. But if we choose the keyword with to introduce an anonymous block, it comes out rather nicely: continue with 2 That's easier to read than continue 2, in my opinion. (If it's not too cute for you.) Or perhaps: continue yield 2 This would create some symmetry, since generators will retrieve the value passed by a continue statement using a yield expression. Shane ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
Tom Rothamel a écrit : I have a question/suggestion about PEP 340. As I read the PEP right now, the code: while True: block synchronized(v1): if v1.field: break time.sleep(1) Will never break out of the enclosing while loop. This is because the break breaks the while loop that the block statement is translated into, instead of breaking the outer True statement. Well, that's exactly what it is intended to do and what I would expect it to do ! break/continue affect only the inner-most loop. Am I understanding this right, or am I misunderstanding this? If I am understanding this right, I would suggest allowing some way of having the iterator call continue or break in the enclosing context. (Perhaps by enclosing the entire translation of block in a try-except construct, which catches Stop and Continue exceptions raised by the generator and re-raises them in the outer context.) I hope this helps. I don't want it like that ! This would differ with the break/continue used in other loops. If you need to break from many loops, enclose them into a function and return from it ! Pierre -- Pierre Barbier de Reuille INRA - UMR Cirad/Inra/Cnrs/Univ.MontpellierII AMAP Botanique et Bio-informatique de l'Architecture des Plantes TA40/PSII, Boulevard de la Lironde 34398 MONTPELLIER CEDEX 5, France tel : (33) 4 67 61 65 77fax : (33) 4 67 61 56 68 ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
Pierre == Pierre Barbier de Reuille [EMAIL PROTECTED] writes: Pierre Tom Rothamel a écrit : I have a question/suggestion about PEP 340. As I read the PEP right now, the code: while True: block synchronized(v1): if v1.field: break time.sleep(1) Will never break out of the enclosing while loop. Pierre Well, that's exactly what it is intended to do and what I would Pierre expect it to do ! break/continue affect only the inner-most Pierre loop. Yeah, but block synchronized(v1) doesn't look like a loop. I think this might be a common stumbling block for people using this construct. Skip ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
Skip Montanaro a écrit : [...] Yeah, but block synchronized(v1) doesn't look like a loop. I think this might be a common stumbling block for people using this construct. Skip Well, this can be a problem, because indeed the black-statement introduce a new loop construct in Python. That's why I advocated some time ago against the introduction of a new name. IMHO, the for-loop syntax can be really used instead of blocks as its behavior if exactly the one of a for-loop if the iterator is an iterator-for-for and the current for-loop cannot be used with iterator-for-blocks. The main problem with this syntax is the use of the blocks for things that are not loops (like the synchronize object)! And they are, indeed, quite common ! (or they will be :) ). Pierre -- Pierre Barbier de Reuille INRA - UMR Cirad/Inra/Cnrs/Univ.MontpellierII AMAP Botanique et Bio-informatique de l'Architecture des Plantes TA40/PSII, Boulevard de la Lironde 34398 MONTPELLIER CEDEX 5, France tel : (33) 4 67 61 65 77fax : (33) 4 67 61 56 68 ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
[Skip Montanaro] Yeah, but block synchronized(v1) doesn't look like a loop. I think this might be a common stumbling block for people using this construct. How many try/finally statements have you written inside a loop? In my experience this is extrmely rare. I found no occurrences in the standard library. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
[Skip Montanaro] Yeah, but block synchronized(v1) doesn't look like a loop. I think this might be a common stumbling block for people using this construct. Guido How many try/finally statements have you written inside a loop? Guido In my experience this is extrmely rare. I found no Guido occurrences in the standard library. [Skip again] How'd we start talking about try/finally? Because it provides by far the dominant use case for 'block'. The block-statement is intended to replace many boilerplace uses of try/finally. In addition, it's also a coroutine invocation primitive. To the casual observer, this looks like break should break out of the loop: while True: block synchronized(v1): ... if v1.field: break time.sleep(1) Without 'block' this would be written as try/finally. And my point is that people just don't write try/finally inside a while loop very often (I found *no* examples in the entire standard library). The PEP says: Note that it is left in the middle whether a block-statement represents a loop or not; this is up to the iterator, but in the most common case BLOCK1 is executed exactly once. That suggests to me it's still not clear if the block statement is actually a looping statement. If not, then break should almost certainly break out of the while loop. Dynamically, it's most likely not a loop. But the compiler doesn't know that, so the compiler considers it a loop. BTW, what did you mean by left in the middle mean? I interpreted it as still undecided, but it's an idiom I've never seen. Perhaps it should be replaced by something more clear. It may be a Dutch phrase that doesn't translate to English as wel as I thought. It doesn't exactly mean still undecided but more depends on your POV. I'll use something different, and also clarify that as far as break/continue are concerned, it *is* a loop. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ 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
Re: [Python-Dev] PEP 340: Breaking out.
Guido van Rossum wrote: [Skip Montanaro] Guido How many try/finally statements have you written inside a loop? Guido In my experience this is extrmely rare. I found no Guido occurrences in the standard library. How'd we start talking about try/finally? Because it provides by far the dominant use case for 'block'. The block-statement is intended to replace many boilerplace uses of try/finally. In addition, it's also a coroutine invocation primitive. I would expect programmers to do more than only replace existing try/finally blocks. The support for RAII patterns in Python might result in more use of RAII primitives and some may fit very well inside a loop. It might not be a bad idea to look at what other languages are doing with RAII. Also, even if there's no occurence right now in the standard library, it doesn't mean it has always been the case in the code evolution, where debugging such pitfall would not be cool. FWIW, I expect most generators used in block-syntax to not be loops. What would imply to support these to pass break to parent loop at run-time? Maybe generators are not the way to go, but could be supported natively by providing a __block__ function, very similarly to sequences providing an __iter__ function for for-loops? We could avoid explaining to a newbie why the following code doesn't work if opening could be implemented in way that it works. for filename in filenames: block opening(filename) as file: if someReason: break By the way, FWIW, my preference if to have no keyword, making it clearer that some block statements are loops and others not, but probably amplifying the break problem. Regards, Nicolas ___ 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