PEP-315 ("do" loop)

W

Wayne Folta

Two observations about PEP-315:

1. It's clever, addresses a definite "wart", and is syntactically
similar to try/except. But it's syntax seems like an acquired taste to
me.

2. It is a very general construct, which might be what is called for.
But I wonder if most of the time it would be used to accomplish
something like:

while 1:
line = sys.stdin.readline()
if line == "\n":
break

In a neater way? How about, instead, creating an "until" loop:

until line == "\n":
line = sys.stdin.readline()

Would be defined to work exactly like a while loop except the test is
not evaluated the first time through the loop. Wouldn't this be akin to
checking at the end of the loop, while maintaining a more while-ish
syntax?

Is this at all useful or is something of the order of PEP-315 the way
to go?
 
R

Raymond Hettinger

[Wayne Folta]
Two observations about PEP-315:
.. . .
In a neater way? How about, instead, creating an "until" loop:

until line == "\n":
line = sys.stdin.readline()

Would be defined to work exactly like a while loop except the test is
not evaluated the first time through the loop. Wouldn't this be akin to
checking at the end of the loop, while maintaining a more while-ish
syntax?

While it works, or should I say "until it doesn't work", there are two
issues. First, this is not the usual meaning of "until" in other
languages where the semantics is like "while" with the condition
inverted. Second, it is much more clear to put the condition at the
point in the program that it gets evaluated (at the end of the loop,
not the beginning).


Raymond Hettinger
 
J

John Roth

Two observations about PEP-315:

1. It's clever, addresses a definite "wart", and is syntactically similar to
try/except. But it's syntax seems like an acquired taste to me.

2. It is a very general construct, which might be what is called for. But I
wonder if most of the time it would be used to accomplish something like:

while 1:
line = sys.stdin.readline()
if line == "\n":
break

In a neater way? How about, instead, creating an "until" loop:

until line == "\n":
line = sys.stdin.readline()

Would be defined to work exactly like a while loop except the test is not
evaluated the first time through the loop. Wouldn't this be akin to checking
at the end of the loop, while maintaining a more while-ish syntax?

Is this at all useful or is something of the order of PEP-315 the way to go?

[response]

1. I've reindented your examples - they don't indent properly under some
browser.

2. Please use plain text - the reason your message isn't quoted properly is
that you used something else, and my news client breaks the formatting.

Now to the substantive responses.

1. The proposed syntax breaks Python's indentation scheme in a manner that
try-except, for-else, while-else, and if-elif-else do not.

2. What I find more serious is that there are a huge number of ways to go in
"improving" the basic while loop, none of which seem to be a natural
stopping point. Python's philosophy seems to be to find the "sweet spot"
where you gain the most leverage with the minimum amount of mechanism.
Neither PEP-315 nor any of the "improvements" I've seen do that.

John Roth
 
J

Jeremy Fincher

Wayne Folta said:
2. It is a very general construct, which might be what is called for.
But I wonder if most of the time it would be used to accomplish
something like:

while 1:
line = sys.stdin.readline()
if line == "\n":
break

If you're concerned about the "beauty" of such code, then the
appropriate way to rewrite it is with a custom iterator/generator.

def untilBlankLine(fh):
line = fh.readline()
while line != '\n':
yield line
line = fh.readline()

And then you can use it like so:

for line in untilBlankLine(sys.stdin):
doSomething(line)

And remember, you can also create custom iterators with the builtin
iter:

for line in iter(sys.stdin.next, '\n'):
doSomething(line)

So I really see no need for any more complex looping construct. The
further we get from encouraging the use of while instead of for, the
better.

Jeremy
 
A

Andrew Clover

John Roth said:
1. The proposed syntax breaks Python's indentation scheme in a manner that
try-except, for-else, while-else, and if-elif-else do not.

I don't know about 'breaks', but IMO the main disadvantage of the 315
proposal is that you have to read code backwards. That is, given:

# Comment
#
while condition:
loop_body

you have to scan backwards to see whether the while block is stand-alone or
part of a do...while construct.

This could be solved by starting with a 'while' construct as normal and then
following it with the new keyword:

while True:
setup_condition
anwhile condition:
loop_body

('anwhile' is by analogy with 'elif', but anything could be used.)

This also has the advantage that more than one anwhile clause could be used,
giving a general-purpose multi-test loop.

Wayne's 'until' proposal is simpler than 315 and only allows a post-test,
not a mid-test loop.

IMO the word 'until' is not a good choice as it inverts the condition logic:
now the condition must be False to continue the loop instead of True as with
'while' and 'if'. If the difference is just that the loop executes at least
once without checking the condition, we could do it with a variant of while
syntax, for example:

while condition, 1:
loop_body

(PXTL has something like this: px:while elements may have a 'min' attribute
giving a minimum number of untested iterations. Seems to work OK, though I
have never had cause to use a number other than 1.)
2. What I find more serious is that there are a huge number of ways to go in
"improving" the basic while loop, none of which seem to be a natural
stopping point.

Indeed. I would quite like to use 'anwhile', but only *quite* - It's a *bit*
nicer than "if not condition: break", but not enormously so.

At best, I'm +0 on loop enhancements in general.
 
A

Andrew Koenig

This could be solved by starting with a 'while' construct as normal and
then
following it with the new keyword:

while True:
setup_condition
anwhile condition:
loop_body

('anwhile' is by analogy with 'elif', but anything could be used.)

Hmmm... You could spell it "and while" without needing a new keyword at all.
Moreover, if you were to define "while:" as equivalent to "while True:",
then you could do this:

while:
setup_condition
and while condition:
loop_body

No reading backwards needed.
 
P

Paul Rubin

John Roth said:
2. It is a very general construct, which might be what is called for. But I
wonder if most of the time it would be used to accomplish something like:

while 1:
line = sys.stdin.readline()
if line == "\n":
break

In a neater way? How about, instead, creating an "until" loop:

until line == "\n":
line = sys.stdin.readline()

Most other languages have a way to put the test at the bottom of the loop.
Pythonically that could look like:

repeat:
line = sys.stdin.readline()
until: line == '\n'

That would have similar indentation characteristics to try...finally.
 
E

Erik Max Francis

Wayne said:
1. It's clever, addresses a definite "wart", and is syntactically
similar to try/except. But it's syntax seems like an acquired taste to
me.

It's also analogous to the way do...while structures are written in
other languages, as well, so it lends familiarity by import.

I personally support the PEP, particularly with its generality.
In a neater way? How about, instead, creating an "until" loop:

until line == "\n":
line = sys.stdin.readline()
[inserted indentation manually, didn't come through here]
Would be defined to work exactly like a while loop except the test is
not evaluated the first time through the loop. Wouldn't this be akin
to checking at the end of the loop, while maintaining a more while-ish
syntax?

The problem is it doesn't read like it runs. The suite is executed
_first_, then the test is repeatedly done and the suite is executed if
it is correct, like a while loop. In some sense you have some "voodoo
magic" here because code is not executed in the order you write it.
It's much better when it's written in the order it is executed, at least
as much as is reasonable. The do...while form does that well.

Also, `until' isn't the right word here. "Until x, do y" just means to
repeatedly do y until x becomes true. In analogue with "while x, do y,"
at first glance all it seems is that the `until' construct does the
logical negation of the conditional expression, but nothing else; that
is, it would seem logical to conclude that

until condition:
doSomething

is precisely the same as

while not condition:
doSomething

which is not at all what you mean. This form of `until' is indeed
included in other languages like Perl. (That doesn't mean that Perl's
way is the right way, it's just that this is an area which would be ripe
for confusion.)

You could use some keyword other than `until', but I think the confusion
of ordering is still there. Something gets executed, then a while loop
occurs, the best way to do that is to have that something appear above
the while loop, and that's just what the do...while form accomplishes.
Is this at all useful or is something of the order of PEP-315 the way
to go?

I think the PEP 315 method is superior.
 
A

Andrew Koenig

Most other languages have a way to put the test at the bottom of the loop.
Pythonically that could look like:

repeat:
line = sys.stdin.readline()
until: line == '\n'

That would have similar indentation characteristics to try...finally.

I believe it would be more useful to allow the test to be anywhere in the
loop, not just at the beginning or at the end. Even better would be to
allow more than one test.
 
P

Paul Rubin

Andrew Koenig said:
I believe it would be more useful to allow the test to be anywhere in the
loop, not just at the beginning or at the end. Even better would be to
allow more than one test.

It's already possible to test anywhere in a loop, with "if ... : break".
 
P

Paul Prescod

John said:
1. The proposed syntax breaks Python's indentation scheme in a manner that
try-except, for-else, while-else, and if-elif-else do not.

How so?
2. What I find more serious is that there are a huge number of ways to go in
"improving" the basic while loop, none of which seem to be a natural
stopping point. Python's philosophy seems to be to find the "sweet spot"
where you gain the most leverage with the minimum amount of mechanism.
Neither PEP-315 nor any of the "improvements" I've seen do that.

Could you enumerate some of these? To me, there is only one big flaw of
the while loop: y forcing you to do the test at the top it also forces
you to contort your code by duplicating the setup line. Sometimes
testing at the bottom or in the middle is just the most natural thing.
"break" caters to it but has its own issues (hiding hte loop condition,
double-indenting the exit point, etc.).

I've also heard some complain that "while True" is confusing.

I don't know what other ways of "improving" the loop you're referring to.

Paul Prescod
 
S

Stefan Axelsson

It's also analogous to the way do...while structures are written in
other languages, as well, so it lends familiarity by import.

Which I think is the problem. Python has generators/iterators, which
work very well with the 'for' loop.

Thus the ugliness of e.g:
while True:
line=infile.readline()
if line == '':
break

is an excellent opportunity to introduce generators/iterators in
general (and the built in iterator of files in particular):
for line in infile:
# do stuff


Stefan,
 
J

Josiah Carlson

1. It's clever, addresses a definite "wart", and is syntactically
similar to try/except. But it's syntax seems like an acquired taste to me.

Clever, perhaps. Ugly and confusing, yes. Solves a 'problem' that
isn't a problem, most definitely.

while 1:
line = sys.stdin.readline()
if line == "\n":
break

I use these all the time, and find them conceptually convenient. Most
Junior/Senior undergraduate computer science majors have no problems
understanding this concept, so I don't think it is necessary to change
the while syntax.

until line == "\n":
line = sys.stdin.readline()

Would be defined to work exactly like a while loop except the test is
not evaluated the first time through the loop. Wouldn't this be akin to
checking at the end of the loop, while maintaining a more while-ish syntax?

As others have said, it is not obvious that until implies "don't test
the condition the first time through".

Is this at all useful or is something of the order of PEP-315 the way to
go?

Personally, I find altering the syntax of while, or adding the 'do' to
be a wart. I've never had problems understanding or writing code like
the following;
while 1:
#setup
if <condition>: break
#body

If I had a vote, I'd be -1 on PEP 315.

- Josiah
 
V

Ville Vainio

Josiah> Personally, I find altering the syntax of while, or adding
Josiah> the 'do' to be a wart. I've never had problems
Josiah> understanding or writing code like the following; while 1:
Josiah> #setup if <condition>: break #body

Josiah> If I had a vote, I'd be -1 on PEP 315.

Amen to that! I think this is only a matter of education. People
should be told that 'while 1' construct is a good, simple, pythonic
way to do the thing. They are often prejudiced, thinking that there is
something 'wrong' with the construct. Hearing that it's ok to do
things this way can actually be very liberating: there is no reason to
feel guilty, and they will quite soon learn to appreciate how natural
and versatile the construct is.

Naming it 'loop' would drive the point even further, of course.
 
J

Josiah Carlson

Amen to that! I think this is only a matter of education. People
should be told that 'while 1' construct is a good, simple, pythonic
way to do the thing. They are often prejudiced, thinking that there is
something 'wrong' with the construct. Hearing that it's ok to do
things this way can actually be very liberating: there is no reason to
feel guilty, and they will quite soon learn to appreciate how natural
and versatile the construct is.

Naming it 'loop' would drive the point even further, of course.

The nice thing about while is that it is general. You can put anything
that returns some value that can be tested for truthfulness, even 1 (as
we like to do). Changing the name alters the linguistic interpretation
of what goes on. Using "loop" would suggest a subsequent "until":

loop:
#setup
#loop internals
until <failure condition> | <not successful condition>

Which is clearer, but adds two keywords. Though, like I said before,
the while setup is perfectly understandable.

- Josiah
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top