Loop until condition is true

R

Remi Villatel

Hi there,

There is always a "nice" way to do things in Python but this time I can't
find one.

What I'm trying to achieve is a conditionnal loop of which the condition
test would be done at the end so the loop is executed at least once. It's
some way the opposite of "while".

So far, all I got is:

while True:
some(code)
if final_condition is True:
break
#
#

What I don't find so "nice" is to have to build an infinite loop only to
break it.

Is there a better recipe?
 
D

Donn Cave

Quoth Remi Villatel <maxilys@SPAMCOP_tele2.fr>:

| What I'm trying to achieve is a conditionnal loop of which the condition
| test would be done at the end so the loop is executed at least once. It's
| some way the opposite of "while".
|
| So far, all I got is:
|
| while True:
| some(code)
| if final_condition is True:
| break
| #
| #
|
| What I don't find so "nice" is to have to build an infinite loop only to
| break it.
|
| Is there a better recipe?

It depends, but that isn't too bad. The alternative would be flag
variable, like "looping = 1; while looping: ..."

The construct you're looking for is "until" in C, and there have been
plenty of proposals to add this or other improvements to Python's
repertoire. As far as I know, it hasn't happened because it isn't
really needed. If you look at C code, at least in my experience the
"until" loop is quite rarely used. (I don't see it once in the source
to Python 2.4, for example.) Meanwhile, the "while True" (or "while 1")
idiom is very familiar to Python programmers (just as the Python source
has dozens of "for (;;)"), so it's preferred for legibility. It's nice,
don't worry.

Donn Cave, (e-mail address removed)
 
P

Peter Otten

Donn said:
If you look at C code, at least in my experience the
"until" loop is quite rarely used.  (I don't see it once in the source
to Python 2.4, for example.)

Long time no C?

'until' in C is actually

do
statement
while (expression);

I found 136 occurrences of "do {" versus 754 of "while (" and 1224 of "for
(" in the Python 2.4 source, so using these rough estimates do-while still
qualifies as "rarely used".

Peter
 
G

Grant Edwards

Long time no C?

'until' in C is actually

do
statement
while (expression);

I found 136 occurrences of "do {" versus 754 of "while (" and 1224 of "for
(" in the Python 2.4 source, so using these rough estimates do-while still
qualifies as "rarely used".

AFAICT, the main use for do/while in C is when you want to
define a block of code with local variables as a macro:

#define DoSomething(foo) \
do \
{ \
int i; \
/* do something with foo and i */ \
} while (0)
 
T

Tim Williams

----- Original Message -----
There is always a "nice" way to do things in Python but this time I can't
find one.
So far, all I got is:

while True:
some(code)
if final_condition is True:
break
#
#

What I don't find so "nice" is to have to build an infinite loop only to
break it.

If your final_condition is already defined outside the "while" then how
about

while not final_condition:
some(code)

Simplistically, this equates to
.... x += 1
....5

:)
 
D

Donn Cave

Quoth Peter Otten <[email protected]>:
....
| 'until' in C is actually
|
| do
| statement
| while (expression);

Oops. Well, QED - I sure don't need it often.

Donn Cave, (e-mail address removed)
 
A

Andrea Griffini

AFAICT, the main use for do/while in C is when you want to
define a block of code with local variables as a macro:

When my job was squeezing most out of the CPU (videogame
industry) I remember that the asm code generated by

while (sz-- > 0)
{
/* do some stuff */
}

was indeed worse than

do
{
/* do some stuff */
} while (--sz);

because of the initial "empty-loop" test (conditional jumps
were bad, and forward conditional jumps were worse).
So where at least one iteration was guaranteed the do-while
loop was a better choice.

Also I've been told there were compilers that if using
for or while loops the generated code was

<initialize>
L1:
<evaluate condition>
je L2
<body>
jmp L1
L2:

Instead the do-while loop would have been

L1:
<body>
<evaluate condition>
jne L1

I.e. the code was better *for each iteration* (one conditional
jump instead of one conditional jump and one inconditional jump).

I think compiler got better since then, even if I don't think
they already so smart to be able to infer the "one interation
guaranteed" property to avoid the initial test that often.

Andrea
 
M

Michael J. Fromberger

Andrea Griffini said:
When my job was squeezing most out of the CPU (videogame
industry) I remember that the asm code generated by

while (sz-- > 0)
{
/* do some stuff */
}

was indeed worse than

do
{
/* do some stuff */
} while (--sz);

because of the initial "empty-loop" test (conditional jumps
were bad, and forward conditional jumps were worse).
So where at least one iteration was guaranteed the do-while
loop was a better choice.

Hmm. I don't know what compiler you were using, but in my experience
it's fairly typical to compile while(<test> ...) { <body> ... } as

j test
body: <body>
...
test: <test>
...
je body ;; or whatever your condition is

To turn this into a do { <body> ... } while(<test> ...), you need only
remove the initial "j test" instruction. Even if forward conditional
jumps are bad for your particular architecture, this method avoids the
problem neatly.

Personally, I'd be pretty suspicious of the quality of a compiler that
produced radically different code for these two constructs without some
damned good reason.

-M
 
J

Joseph Garvin

Peter said:
I found 136 occurrences of "do {" versus 754 of "while (" and 1224 of "for
(" in the Python 2.4 source, so using these rough estimates do-while still
qualifies as "rarely used".

Peter
That's 136 times you'd have to use an ugly hack instead. I definitely
wouldn't mind an until or do/while.
 
R

Ron Adam

Joseph said:
That's 136 times you'd have to use an ugly hack instead. I definitely
wouldn't mind an until or do/while.

I would happy with just having while: without a 1 or True to indicate a
continuous loop. Having a if-break at the end doesn't bother me at all.

while:
<suite>
if <condition>: break

Being able to move the break point to where it's needed or have more
than one is a feature and not a problem. IMHO of course.

It also has the benefit that you have the option to do an extra bit of
cleanup between the if and the break if you need to. The until or
do-while doesn't give you that option.

I suppose if an until <condition>: <suite>, could be made to be more
efficient and faster than an if <condition>: <suite>; break, then I'd
be for that.

while:
<suite>
until <condition>[: suite] # optional suite or block
<suite>

But I doubt it would be significantly faster than an if statement with a
break. So the only benefit I see is you don't have to use the break
keyword, and the exit conditions will stand out in blocks with a lot of
if statements in them.

Regards, Ron
 
M

Magnus Lycka

Remi said:
while True:
some(code)
if final_condition is True:
break
#
#

What I don't find so "nice" is to have to build an infinite loop only to
break it.

This is a common Python idiom. I think you will get used to it.

Is there a better recipe?

final_condition = False
while not final_condition:
some(code)
 
B

Benji York

Cyril said:
Another question could be: why is there not a statement "whileTrue" or
"loop"?

I don't think the saving of a single space to transform "while True:"
into "WhileTrue:" is really worth it. The same goes for "loop", the
added complexity to the language (as little as it is) isn't rewarded by
a large enough improvement to make it worth it.
It could be an economy of one unuseful test by loop.

If by "economy" you mean "optimization", then I would suggest that the
difference would be unnoticeable.
 
M

Magnus Lycka

Benji said:
If by "economy" you mean "optimization", then I would suggest that the
difference would be unnoticeable.

If there is a measurable performance gain in skipping the runtime
test in "while True", then this is a compiler issue, not a language
issue. I don't know anything about the Python compiler internals,
but it doesn't seem very hard to identify simple literals following
while and if, and to skip the runtime test. (Perhaps it's done
already?)

I hope the time is over when language designers build ugly quirks
into programming language syntaxes to make life a little easier for
the compilers.
 
C

Charles Krug

This is a common Python idiom. I think you will get used to it.



final_condition = False
while not final_condition:
some(code)

To the OP, don't get hung up on the syntax we use to implement a loop.

I took my first programming class long enough ago that we had to do
things like this (roughly translating the FORTRAN IV I remember into
p-code)

To do:

while TrueCondition
(loop body)

we'd have to write:

TopOfLoop:
if not TrueConditional goto loopEnd
(loop body)
goto TopOfLoop

loopEnd:

We were even required to write our source twice:

The first pass was "structured" and had to be proven correct.

The second pass was translated into something our compiler supported.

We still called it a "while loop" even though the syntax was icky.

When C came out with its built in looping, it was an unbelievable
luxury.
 
F

Fredrik Lundh

Remi said:
There is always a "nice" way to do things in Python but this time I can't
find one.

What I'm trying to achieve is a conditionnal loop of which the condition
test would be done at the end so the loop is executed at least once. It's
some way the opposite of "while".

So far, all I got is:

while True:
some(code)
if final_condition is True:
break
#
#

What I don't find so "nice" is to have to build an infinite loop only to
break it.

checking if a logical expression is true by comparing it to True is bad
style, and comparing values using "is" is also bad style.

the correct way to write that if-statement is:

if final_condition:
break

and yes, the "infinite" while loop is a standard Python pattern. get
used to it.

</F>
 
K

Konstantin Veretennicov

I don't know anything about the Python compiler internals,
but it doesn't seem very hard to identify simple literals following
while and if, and to skip the runtime test. (Perhaps it's done
already?)

True doesn't seem to be a literal, it is looked up by name and can be
rebound to, say, 0 anytime:
6 JUMP_IF_FALSE 4 (to 13)
9 POP_TOP
10 JUMP_ABSOLUTE 3
...

OTOH,
...

- kv
 
M

Magnus Lycka

Konstantin said:
True doesn't seem to be a literal, it is looked up by name and can be
rebound to, say, 0 anytime:

Right. Silly me. Maybe in some future Python version, True and False
will be constants, like None is since Python 2.4.
 
S

Stelios Xanthakis

Magnus said:
Right. Silly me. Maybe in some future Python version, True and False
will be constants, like None is since Python 2.4.

Actually, there is support in marshal to write True and False objects so
I don't understand why this isn't in 2.4

Anyway, if you can't wait for 2.5 either use 'while 1:', or pyc[1]

Stelios

[1] http://students.ceid.upatras.gr/~sxanth/pyc/
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top