statements in control structures (Re: Conditional Expressions don't solve the problem)
Andrew Dalke
dalke at dalkescientific.com
Wed Oct 17 20:58:07 EDT 2001
Huaiyu Zhu:
> cannot be written in this naive version:
>
> while 1:
> x = next()
> if x.is_end: break
> y = process(x)
> if y.is_what_we_are_looking_for(): break
> else:
> raise "not found"
>
> This is because there are two breaks that have different semantical
> meanings. The fully equivalent version in current syntax has to
use
> one extra variable to keep track of the breaks that affect the else
It doesn't have to use an extra variable.
while 1:
x = next()
if x.is_end:
raise "not found"
y = process(x)
if y.is_what_we_are_looking_for():
break
> 4.1. Action needed before condition:
>
> while x = get_next(); x:
> whatever(x)
I prefer the syntax mentioned some months ago when this discussion
last flared up.
loop:
x = get_next()
break if x:
whatever(x)
(with variations of the spelling - I don't recall the details
of what came up)
Basically, I don't like multiple actions in the same line. I
like vertical arrangement of code. I find it easier to read and
easier to understand.
> 4.2. Condition does not need to be a method of an object in assignment:
>
> while line = readline(); 'o' in line:
> line = process(line)
> if 'e' in line: break
> else:
> print "never met break"
for line in iter(readline, ""):
if 'o' in line:
print "never met break" # Really, "never saw an 'e'"
break
line = process(line)
if 'e' in line:
break
This one extra line if you (unlike me) put the 'break' after
if's ":".) And since you like code after semicolon,
for line in iter(readline, ""):
if 'o' in line:
print "never saw an 'e'"; break
line = process(line)
if 'e' in line:
break
> 4.4. More complex example:
>
> if x = dict[a]; x: proc1(x)
> elif x = next(x); x.ok(): proc2(x)
> elif x.change(); property(x): proc3(x)
> ...
Need a real life example here. Is there something in the standard
library which would be improved with this change? The reason I
ask is because this code can be refactored into a function.
def funky_function(dict, a, x):
x = dict[a]
if x:
return proc1(x)
x = next(x)
if x.ok():
return proc2(x)
x.change()
if property(x):
return proc3(x)
You can add qualifications to make a function call harder to do,
but I'm betting they aren't common in real life.
> It is seen that the new syntax remove substantial amount of clutter,
in contrived cases
> thereby increasing readability and expressiveness.
but increasing the temptation for people to write
a = f(x)
if a > 2:
g()
as
if a = f(x); a > 2:
g()
which is *less* readable because it is *more* expressive.
> This structure is safe against single typing errors:
Here's a single typing error.
if x > 1;0:
...
when it should have been
if x > 1.0:
...
> - mistype == for = in statement will be detected
How? An expression is a statement.
> Since the change is only in the syntax of "if", "elif" and "while",
> not in the fundamentals of expressions and statements, there is not
> much more chance of obfuscation than existing syntax.
Famous last words. :)
Quick! Spot the colon!
if a; \
b; \
c; \
d: \
e; \
f; \
g
This isn't possible now because the first ";" or ":"-like symbol after
the 'if' must be a ':' else Python would complain.
> We show that the following alternatives have more problems than the
> proposed extension.
...
> 6.3. Using iterators: In Python 2.2, it is possible to write
>
> for line in file:
> if line=='end': break
> process_line(line)
>
> in place of
>
> while line=file.readline(); line != 'end':
> process_line(line)
>
> However, this does not solve the problem we are considering
> completely. It is more suitable for objects that are naturally used
> (and reused) in iterations so that it is profitable to create
> iterators for them. It is not practical to define an iterator for
> every action that might go before a condition:
>
> while char=file.readline()[3]; char != 'x':
> process(char)
To quote Winnie-the-Pooh, I am a programmer of very little brain.
I forget things too easily, so I like to step through what I'm doing.
for line in iter(file.readline, ""):
char = line[3]
if char != 'x':
break
process(char)
This is also easier to debug. I can stick in a "print line" and
see what's going on. It calls for more work to change the original
code to do that.
Yes, it's 5 lines compared to 2. Again, your example is contrived.
The real code might look like
commands = (
(3, 'x', None),
(0, 'reset', do_reset),
(4, 'fly', use_swatter),
)
for line in file:
for cmd in commands:
if line[cmd[0]:].startswith(cmd[1]):
f = cmd[2]
if f is None:
return
f(line)
> while string = raw_input(prompt): not
string.startswith("n"):
> process(string)
Should be a semicolon there ;)
You didn't mention
loop:
statements
break if expr:
statements
as an alternative, with various spellings of 'loop' and 'break if'.
One with no new keywords is
while expr:
statements
break if expr:
statements
but all this does is save one line over
while expr:
statements
if expr:
break
But-then-again-it-took-me-a-while-to-like-list-comprehensions-ly y'rs
Andrew
dalke at dalkescientific.com
More information about the Python-list
mailing list