Nick Coghlan wrote:
> Iterating over a sequence. If it's single-pass (and always single pass), you > should use a user defined statement instead. > That's the technique suggested for the single-pass user defined statements. > However, a 'for loop with finalisation' is *still fundamentally an iterative > loop*, and the syntax should reflect that. <in responce to do> > The same keyword cannot be used for the looping vs non-looping construct, > because of the effect on the semantics of break and continue statements. I disagree with this, I think 'do' would work very well for both single pass, and multiple pass, blocks. In this example 'do' evaluates as True until the generator ends without returning a value: def open_file(name,mode): f = open(name,mode) try: yield f finally: f.close() Do f from open_file(name,mode): for line in f: print line.rstrip() On the first try, it gets f, so the do expression evaluates as True and the BLOCK is run. On the second try, instead of getting a value, the finally suite is executed and the generator ends, causing the do expression to evaluate as False. If a continue is used, it just skips the end of the 'do' body, and then weather or not to loop is determined by weather or not the 'do expression evaluates as True or not. A break skips the rest of the 'do' body and execute the generators finally. This works the same in both single pass and multi pass situations. The difference is by using a truth test instead of iterating, it better represents what is happening and opens up a few options. There's also the possibility to use conditional looping based on the value returned from the generator. do VAR from EXPR if VAR==CONST: BLOCK This is a bit verbose, but it reads well. :-) But that is really just a short cut for: do VAR from EXPR: if VAR != CONST: break BLOCK The Syntax might be: do ([VAR from] EXPR1) | (VAR from EXPR1 if EXPR2): BODY >>I don't have an opinion on user defined statements yet. But I think >>they would be somewhat slower than a built in block that does the same >>thing. > > What do you mean by 'built in block'? The user defined statements of the PEP > redraft are simply a non-looping version of PEP 340's anonymous block > statements. Ok, my mistake, I thought you were suggesting the more general user defined statements suggested elsewhere. > No, the else clause on loops is a little known part of present day Python - > it > executes whenever the loop terminates naturally (i.e. not via a break > statement). Hmm... ok, and the opposite of what I expected. No wonder its a little known part. > My PEP redraft, on the other hand, suggests the introduction of a 'for loop > with > finalisation' that works fairly similarly to PEP 340's anonymous block > statements. Here is my current thinking. It will be better to have 3 separate loops with three identifiable names, and have each work in distinctly different ways. That simplifies, teaching, using, and reading the resulting code. IMHO. 1. For-loops: Fast efficient list iteration. No changes. 2. While-loops: Fast efficient truth test based loop. No changes. 3. Do-loops: An generator based loop with finalization: This could be both single and multiple pass. The difference is determined by weather or not the generator used loops the yield statement or not. I think a good test is the retry example in the PEP. A solution that can represent that clearly and concisely would be a good choice. Maybe this could be made to work: def auto_retry(n, exc): while n>0: try: yield True n = 0 except exc: n -= 1 do auto_retry(3, IOError): f = urllib.urlopen("http://python.org/") print f.read() The ability to propagate the exception back to the generator is what's important here. The while version of this nearly works, but is missing the exception propagation back to the generator, the ability to pass back through the yield, and finalization if the outside while loop is broken before the generator finishes. def auto_retry(n, exc): while n>1: try: yield True break except exc: n -= 1 # finalize here yield None import urllib ar = auto_retry(3, IOError) while ar.next(): f = urllib.urlopen("http://python.org/") print f.read() Although changing 'while' shouldn't be done. I think using 'do' for generator based loops would be good. This isn't that different from PEP340 I think. Maybe it's just comming to the same conclusion from a differnt perspective. <shrug> :-) Cheers, Ron _______________________________________________ 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