By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,928 Members | 1,173 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,928 IT Pros & Developers. It's quick & easy.

PEP-0315--Enhanced While Loop: An idea for an alternative syntax

P: n/a
PEP 315 suggests that a statement such as

do:
x = foo()
while x != 0:
bar(x)

be equivalent to

while True:
x = foo()
if x == 0:
break
bar(x)

I like the overall idea, but wonder about the extra keyword. Moreover, if
you see

x = foo()
while x != 0:
bar(x)

you have to read backward to see whether the assignment to x is part of this
statement or part of a previous statement.

I have a proposal for an alternative syntax that solves both of these
problems:

while:
x = foo()
and while x != 0:
bar(x)

This example actually incorporates two changes:

1) "while:" is equivalent to "while True:"

2) "and while <condition>:" is an exit from the middle of the loop,
analogously to PEP 315.

My proposal allows for multiple exits in the obvious way

while <condition 1>:
<statements 1>
and while <condition 2>:
<statements 2>
and while <condition 3>:
<statements 3>
...

in which all of the conditions and statements are evaluated in the order
shown until a condition is false, at which point the loop terminates.
It also occurs to me that this notion can be generalized to include "or
while" as well as "and while". Using "or while" would implement a control
structure that Dijkstra proposed in "A Discipline of Programming". The idea
would be that

while <condition 1>:
<statements 1>
or while <condition 2>:
<statements 2>
or while <condition 3>:
<statements 3>

would be equivalent to

while True:
if <condition 1>:
<statements 1>
elif <condition 2>:
<statements 2>
elif <condition 3>:
<statements 3>:
else:
break

This notion is still partly baked, if for no other reason than that I'm not
sure how a statement with both "or while" and "and while" clauses should
work. My first thought is for "and while" to have priority over "or while",
analogously with expressions, but then the following example came to me.
It's the inner loop of a binary search:

while low < hi:
mid = (low + hi) // 2;
and while value < table[mid]:
high = mid
or while value > table[mid]
low = mid

If "and" has higher precedence than "or", this example doesn't work. So I'm
not sure about its merits -- but I'm mentioning it in case someone else can
improve on it.
Jul 18 '05 #1
Share this Question
Share on Google+
24 Replies


P: n/a
"Andrew Koenig" <ar*@acm.org> writes:
PEP 315 suggests that a statement such as

do:
x = foo()
while x != 0:
bar(x)


I'm still scratching my head over that PEP. Got a real-world code sample
that it would improve?
Jul 18 '05 #2

P: n/a
Paul Rubin wrote:
I'm still scratching my head over that PEP. Got a real-world code
sample
that it would improve?


do:
line = inputFile.readline()
while line:
...
line = inputFile.readline()

--
__ Erik Max Francis && ma*@alcyone.com && http://www.alcyone.com/max/
/ \ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
\__/ The doors of Heaven and Hell are adjacent and identical.
-- Nikos Kazantzakis
Jul 18 '05 #3

P: n/a
Erik Max Francis wrote:
Paul Rubin wrote:
I'm still scratching my head over that PEP. Got a real-world code
sample
that it would improve?


do:
line = inputFile.readline()
while line:
...
line = inputFile.readline()


Man, what a perfect gaffe on my part. The purpose of the do...while
construct is to _eliminate_ the duplication. This should be:

do:
line = inputFile.readline()
while line:
...

--
__ Erik Max Francis && ma*@alcyone.com && http://www.alcyone.com/max/
/ \ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
\__/ The doors of Heaven and Hell are adjacent and identical.
-- Nikos Kazantzakis
Jul 18 '05 #4

P: n/a
Erik Max Francis <ma*@alcyone.com> writes:
do:
line = inputFile.readline()
while line:
...
line = inputFile.readline()


So it's yet another workaround for Python's lack of assignment
expressions. I like

while (line := inputFile.readline()):
...

a lot better.
Jul 18 '05 #5

P: n/a
Paul Rubin wrote:
So it's yet another workaround for Python's lack of assignment
expressions. I like

while (line := inputFile.readline()):
...

a lot better.


(Please check my correction, it's actually not as dumb as I suggested.)

--
__ Erik Max Francis && ma*@alcyone.com && http://www.alcyone.com/max/
/ \ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
\__/ The doors of Heaven and Hell are adjacent and identical.
-- Nikos Kazantzakis
Jul 18 '05 #6

P: n/a
Erik Max Francis <ma*@alcyone.com> writes:
Man, what a perfect gaffe on my part. The purpose of the do...while
construct is to _eliminate_ the duplication. This should be:

do:
line = inputFile.readline()
while line:
...


I still like the assignment expression better.
Jul 18 '05 #7

P: n/a
In article <7x************@ruckus.brouhaha.com>, Paul Rubin wrote:
Joe Mason <jo*@notcharles.ca> writes:
> There's nothing implicit about an assignment expression.


Except the return value.


Huh? It's an expression, the value is explicit.


x = 1 (or x := 1) looks to me like a statement that sets x to 1, not an
expression. I wouldn't expect any return value, if my mind hadn't been
corrupted by C. So the fact that there's a return value at all is
implicit.

Joe
Jul 18 '05 #8

P: n/a
Joe Mason <jo*@notcharles.ca> writes:
x = 1 (or x := 1) looks to me like a statement that sets x to 1, not an
expression. I wouldn't expect any return value, if my mind hadn't been
corrupted by C. So the fact that there's a return value at all is
implicit.


What do you mean by "return value"? Only functoins have return
values. It's just a value, not a return value.
Jul 18 '05 #9

P: n/a
Paul Rubin wrote:
What do you mean by "return value"? Only functoins have return
values. It's just a value, not a return value.


You know very well what he means, you're just being difficult at this
point.

What you're suggesting has been proposed, time and time again. And it
has been shot down, time and time again.

--
__ Erik Max Francis && ma*@alcyone.com && http://www.alcyone.com/max/
/ \ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
\__/ I am a gentlemen: I live by robbing the poor.
-- George Bernard Shaw
Jul 18 '05 #10

P: n/a
In article <7x************@ruckus.brouhaha.com>, Paul Rubin wrote:
Yeah, except now you've bloated up your code with another function.
Assignment expression solves this one too.
Except that the 'bloat' is constant, you only need one function, once
to solve all your 'read'-problems. And hence that function probably
belongs in a library, like it does for 'readline', I have no doubt
that it'll end up there if this situation turns out to be a problem.

Generators/iterators gives you e.g. the opportunity to write:

(Snarfed from <67********************************@4ax.com>, by Dave K
<dk*********@REMOVEhotmail.com>)from sets import Set
file('pruned_ips.txt', 'w').writelines(
Set(file('ips.txt')) - Set(file('excluded_ips.txt')))

This code relies on `writelines' accepting an iterable, sets returning
their members whenever iterated, Set constructors accepting an iterable,
and files returning their lines whenever iterated. And of course, on
`close' rarely being needed in Python! :-)


Something that the assignment as expression doesn't.

I'd say the syntax is just right as it is. No extra complexity in
while loops or assignments as expressions is needed. In fact the
relative awkwardness of the present state serves as an excellent
opportunity to introduce generators/iterators.

Stefan,
--
Stefan Axelsson (email at http://www.cs.chalmers.se/~sax)
Jul 18 '05 #11

P: n/a
Erik Max Francis <ma*@alcyone.com> writes:
What do you mean by "return value"? Only functoins have return
values. It's just a value, not a return value.
You know very well what he means, you're just being difficult at this
point.


No, I think he's preoccupied with distinctions that aren't there.
He said
x = 1 (or x := 1) looks to me like a statement that sets x to 1, not
an expression. I wouldn't expect any return value, if my mind hadn't
been corrupted by C.
but of course from my Lisper's point of view, the whole idea that a
statement and an expression are fundamentally different things is
itself a sign of a corrupted mind. I'm not willing to accept the
notion that the way C does it is the one that's "corrupt". C was
phenomenally successful despite its warts, because it was conducive to
an easy, fluid coding style, just like Python sometimes aspires to.
Assignment expressions were an aspect of that conduciveness. Python
itself has this really odd mixture of wonderful fluidity (I love list
comprehensions), and completely unnecessary, almost Calvinistic
moralizing over semi-trivial issues like assignment expressions, while
still leaving plenty of naked razor blades (unchecked exceptions, the
crazy scoping system, lack of protection on class attributes, etc.)
for the programmer to slash himself with.
What you're suggesting has been proposed, time and time again. And it
has been shot down, time and time again.


I'm unmoved by that observation. We've seen it plenty of times
before, that the need for something in Python was recognized for a
long long time, but shot down repeatedly before finally being fixed
(look at 'a += b'). Maybe this will be the same.
Jul 18 '05 #12

P: n/a
In article <7x************@ruckus.brouhaha.com>, Paul Rubin wrote:
No, I think he's preoccupied with distinctions that aren't there.
He said
x = 1 (or x := 1) looks to me like a statement that sets x to 1, not
an expression. I wouldn't expect any return value, if my mind hadn't
been corrupted by C.


but of course from my Lisper's point of view, the whole idea that a
statement and an expression are fundamentally different things is
itself a sign of a corrupted mind. I'm not willing to accept the


Aha! Now I see. Python is not Lisp. It has tons of imperative
constructs that don't return values. While loops, for instance.

Corrupt or not, though, the Lisp way is "everything implicitly returns a
value". I'm not arguing for or against assignment expressions - I think
it's pretty trivial. I'm just saying you can't claim they aren't
implicit. And the Zen of Python has things to say about that.

As a Lisper, shouldn't you be avoiding assignments because of their
side effects anyway? Surely you should be pushing for "let" bindings.

Speaking of which, even though I'm not particularly interested in new
syntax - break was fine for granpappy, and it's good enough for me -
let wouldn't be a bad keyword for the initialization section of the
loop. Except that wouldn't mean exactly what it does in function
languages, which would be confusing. "with" is another possibility -
the two uses I know are Pascal, where it just makes a record alias, and
Modula-3, where it works differently but I forget how. But it's already
overloaded, anyway.

Joe
Jul 18 '05 #13

P: n/a
Andrew Koenig <ar*@acm.org> wrote:
I have a proposal for an alternative syntax that solves both of these
problems:

while:
x = foo()
and while x != 0:
bar(x)

This example actually incorporates two changes:

1) "while:" is equivalent to "while True:"

2) "and while <condition>:" is an exit from the middle of the loop,
analogously to PEP 315.


I'm -1 on this idea, because "and while" just does not feel Pythonic to
me. I read the code above and see a loop that does "x = foo()" forever,
then when that loop is finished (whenever that may happen) proceeds to
do bar(x) as long as x != 0. In other words, the syntax is very
counter-intuitive to me, and causes me to do a couple of double-takes
before I figure it out.

I've sometimes wished for a construct like do ... while, but I would
rather live without one than have one that's counter-intuitive.

--
Robin Munn
rm***@pobox.com
Jul 18 '05 #14

P: n/a
Joe Mason <jo*@notcharles.ca> writes:
but of course from my Lisper's point of view, the whole idea that a
statement and an expression are fundamentally different things is
itself a sign of a corrupted mind. I'm not willing to accept the
Aha! Now I see. Python is not Lisp. It has tons of imperative
constructs that don't return values. While loops, for instance.


That's merely a side effect of the parser not giving you a way to
capture the value of a while loop. In Lisp, while loops return a
value. In Python, the value is, heh, "implicitly" discarded.
Corrupt or not, though, the Lisp way is "everything implicitly returns a
value". I'm not arguing for or against assignment expressions - I think
it's pretty trivial. I'm just saying you can't claim they aren't
implicit. And the Zen of Python has things to say about that.
Is the value of "2+2" also not implicit by the same logic? You're
using the word implicit in a pretty strange way, I think.
As a Lisper, shouldn't you be avoiding assignments because of their
side effects anyway? Surely you should be pushing for "let" bindings.
Never heard of setq? ;-)
Speaking of which, even though I'm not particularly interested in
new syntax - break was fine for granpappy, and it's good enough for
me - let wouldn't be a bad keyword for the initialization section of
the loop.


I find the proposed new loop syntax very confusing. I do see some
benefit for fixing up the initialization issue but think it should be
done at the top of the loop, not spread all through it. C's 'for'
loop is better, because it puts that stuff at the top.
Jul 18 '05 #15

P: n/a
>>>>> "Andrew" == Andrew Koenig <ar*@acm.org> writes:

Andrew> Any loop that is currently written in the form

Andrew> while True: <statements> if condition: break more
Andrew> statements

Why not just make a new keyword, 'loop', an alias of "while 1"?

Usually it seems that the 'get data to process' is done immediately
after "while 1", and the break immediately after that. It's a good
construct, easy to understand and easy to type (if you use 'while 1'
instead of 'while True', that is - 'while True' seems like a rather
pointless excercise to me).

Also, the proposed construct doesn't IMVHO seem less cryptic at all -
exactly the opposite, in fact.

--
Ville Vainio http://tinyurl.com/2prnb
Jul 18 '05 #16

P: n/a
>>Sure, there is a difference between '==' becoming '=', and '=='
becoming ':=', but the difference is 1 inch and a shift key on my
keyboard.
Oh come on, you're grasping at straws. What about the difference
between '>' and '<'? Those are even closer together than ':' and '='.
Do you want to get rid of those operations too? The '=' vs '==' thing
may actually confuse some people but it's hard to mistake := for
anything other than an assignment.


Who said anything about confusing them? I merely stated that it would
be relatively easy to mistype. If what you are proposing is used, and
people actually try converting their old-style-while to new-style-while,
it would be easy to forget to insert the colon. When writing new loops,
it would also be relatively easy to slip and insert a := when intending
==. Looking at my keyboard, := rather than >= would be even more likely
(or even the reverse), because one already has the shift-key down, and
the keys are adjacent to one another.

You can say that I am grasping at straws, but ignoring mistyping as a
source for bugs, is foolish on your part.

I've made larger errors when typing than just an inch and a
shift-key. I believe it would cause more bugs, reduce readability,
and attempts to fix a problem that doesn't really exist.


That's sheer speculation on your part. You've cited the existence of
assignment expression errors causing 'more than one bug' in the
hundreds of millions of C code written over the past three decades.


I didn't offer more because I've never used the syntax in my C/C++ code,
nor have I waded through millions of lines of C. I also wouldn't want
to go through the potentially thousands of lines where it is used. That
would be a waste of time.

That's not persuasive of anything, given how many other bugs there are
of just about every other sort.
A better statement would have been, "That says nothing about the
proportion of bugs in such assignments, as compared with other
syntactical bugs." Which would be correct. But as I just said, I
haven't waded through millions of lines of C and categorized the types
of syntax bugs. Certainly it is speculation on my part, but it is
conservative speculation.

All proposed methods that ask to change syntax, deviates from Python
style, which /may/ introduce more bugs.

And in fact, the one in the Linux
kernel shows the opposite of what you're claiming. It wasn't an
accidental error that slipped through anything; it was a deliberate
hole that someone introduced hoping no one would notice, but it was
noticed immediately, showing that the =/== distinction is less
difficult to spot than you seem to think.
I never claimed it was difficult to spot. I claimed it was easy to make
such a typing mistake. Certainly the exploit was deliberate, but had
the linux kernel not been as well audited as it is, the bug may have
persisted. In the few thousand lines of C code I wrote during
undergrad, I know I made a handful of == -> = typing errors. I expect
that the occasional slip from one to the other is not uncommon.

Assignment expressions have been used successfully in C and other
languages for many years, including plenty of them in the CPython
code. It's reasonable to say they're used all the time by some very
capable programmers and it's impertinent of you to imply that those
programmers don't know what they're doing.
You seem to like to put words into people's mouths. I never said that C
programmers don't know what they are doing when they are using them. I
said that it would be easy to mistype, and seeks to solve a "problem" in
Python that isn't one.

If you don't like them,
fine, don't use them, but don't try to convince people who use them
that they're wrong.
What people do with other langauges, I do not concern myself with. If
you want to use while (a = b) in other languages, feel free. On the
other hand, when you talk about taking a language that I care about,
that I use on a daily basis for both work and play, and mangle it with
what I consider to be useless syntax, I (and everyone else I expect)
reserve the right to give my opinion. I never said that its use in
other languages was wrong, just that I don't want it in Python. Which
leads me to:

I think PEP 315 is a waste of bits. In my opinion, Python doesn't need
a syntax change for while loops, and those who cannot understand the
flow of:

while 1:
#setup
if <condition to stop>: break
#loop internals

Are operating on a lower conceptual level than the majority of CS
undergrads that I teach on a daily basis at UC Irvine. Now, UCI is a
decent school, so maybe we are setting the bar too high. However, the
above while loop is clearer (even though it is more verbose), than all
of the suggested syntax changes.

What's a programming language like Python aiming
to do, anyway? Among other things, it aims to make programming
non-frustrating. So if a sizeable population of users find that the
absence of a particular useful feature is actually frustrating, give
some thought to the idea that the absence really is a shortcoming in
the language.


I did give some thought to it. I think the bugs that may occur as a
result of its availability would be far more frustrating than the
relatively minor additional typing required for old-style loops.

- Josiah
Jul 18 '05 #17

P: n/a
On 19 Feb 2004 09:29:08 GMT in comp.lang.python, Stefan Axelsson
<sa*@csmisc72.cs.chalmers.se> wrote:

(snip)

Generators/iterators gives you e.g. the opportunity to write:

(Snarfed from <67********************************@4ax.com>, by Dave K
<dk*********@REMOVEhotmail.com>)
from sets import Set
file('pruned_ips.txt', 'w').writelines(
Set(file('ips.txt')) - Set(file('excluded_ips.txt')))

This code relies on `writelines' accepting an iterable, sets returning
their members whenever iterated, Set constructors accepting an iterable,
and files returning their lines whenever iterated. And of course, on
`close' rarely being needed in Python! :-)

Just for the record, that was actually written by François Pinard, not
me. Well worth quoting again, though, as it's a lovely example.
Something that the assignment as expression doesn't.

I'd say the syntax is just right as it is. No extra complexity in
while loops or assignments as expressions is needed. In fact the
relative awkwardness of the present state serves as an excellent
opportunity to introduce generators/iterators.


FWIW, I think I agree with you. I'm no expert on generators, but I do
know one thing - they're *much* more powerful and flexible than I
currently realise :)

Dave

Jul 18 '05 #18

P: n/a
I don't like the syntax. I find the indentation counter-intuitive.
Jul 18 '05 #19

P: n/a
On Wed, 18 Feb 2004 19:10:06 -0600, Jeff Epler <je****@unpythonic.net>
wrote:
On Wed, Feb 18, 2004 at 05:41:10PM +0000, Terry Carroll wrote:
With read() instead of readline(), then.

I've certainly run into this using urllib2.


Push the "yucky" while 1: loop into a generator function,
and then use a regular "for" loop in the multiple places
you need to handle a file in this way:


Sure; there's no question that you can usually move awkward code
constructs to a different location in the program.

Jul 18 '05 #20

P: n/a
The do block is no safeguard against copy errors because it's optional.
A comment saves the same purpose. Replace

do:
init()
while cond():
body()

by

# init while
init()
while cond():
body()
PEP-0315 shouldn't be added to Python.

Mit freundlichen Gruessen,

Peter Maas

--
-------------------------------------------------------------------
Peter Maas, M+R Infosysteme, D-52070 Aachen, Hubert-Wienen-Str. 24
Tel +49-241-93878-0 Fax +49-241-93878-20 eMail pe********@mplusr.de
-------------------------------------------------------------------
Jul 18 '05 #21

P: n/a
Peter Maas <fp********@netscape.net> writes:
The do block is no safeguard against copy errors because it's optional.
A comment saves the same purpose. Replace

do:
init()
while cond():
body()

by

# init while
init()
while cond():
body()

No, you don't understand. The initialization is part of the loop.
That is, the replacement for the do loop is

while 1:
init()
if not cond: break
body()
PEP-0315 shouldn't be added to Python.


I agree, but the reasoning has to go a bit further.
Jul 18 '05 #22

P: n/a
In article <ur********************************@4ax.com>, Dave K wrote:
Just for the record, that was actually written by François Pinard, not
me. Well worth quoting again, though, as it's a lovely example.


Ah, my bad. I thought I cut the right attribution. At least I didn't
claim that *I* had written it. :-)

Stefan,
--
Stefan Axelsson (email at http://www.cs.chalmers.se/~sax)
Jul 18 '05 #23

P: n/a
Paul Rubin wrote:
No, you don't understand. The initialization is part of the loop.
That is, the replacement for the do loop is

while 1:
init()
if not cond: break
body()


You are right, sorry. I was a bit hasty, thanks for the correction.
I reread the PEP and now realize that it is about situations like

<setup code>
while <condition>:
<loop body>
<setup code>

So the setup code is there to guarantee at least one execution
of the loop body. If this is the case, then the proposed form
"do <setup code> while" is misleading in my opinion. I would
merge <setup code> and <loop body> to <theBody> and solve the
problem with code like

do:
<theBody>
breakif <cond>

This would be clearer but I would mind this as well because
I like the minimality of Python and I am completely satisfied
with

while 1:
<theBody>
if <cond>: break

Mit freundlichen Gruessen,

Peter Maas

--
-------------------------------------------------------------------
Peter Maas, M+R Infosysteme, D-52070 Aachen, Hubert-Wienen-Str. 24
Tel +49-241-93878-0 Fax +49-241-93878-20 eMail pe********@mplusr.de
-------------------------------------------------------------------
Jul 18 '05 #24

P: n/a
Peter Maas wrote:
do:
<theBody>
breakif <cond>


I forgot the situation

do:
<Body1>
breakif <cond>
<Body2>

I was totally misguided by the term "setup" for <Body1>. In my
understanding a setup happens once like in C's

for(<setup>;<cond>;<next>)
...

Mit freundlichen Gruessen,

Peter Maas

--
-------------------------------------------------------------------
Peter Maas, M+R Infosysteme, D-52070 Aachen, Hubert-Wienen-Str. 24
Tel +49-241-93878-0 Fax +49-241-93878-20 eMail pe********@mplusr.de
-------------------------------------------------------------------
Jul 18 '05 #25

This discussion thread is closed

Replies have been disabled for this discussion.