[Python-ideas] if condition: break idiom
Josiah Carlson
josiah.carlson at gmail.com
Sun Sep 21 18:48:07 CEST 2008
On Sat, Sep 20, 2008 at 1:26 PM, Arnaud Delobelle
<arnodel at googlemail.com> wrote:
>
> On 20 Sep 2008, at 20:44, Josiah Carlson wrote:
>
>>> On Sat, Sep 20, 2008 at 11:35 AM, Arnaud Delobelle
>>>>
>>>> [...] I think that this would look better:
>>>>
>>>> while True:
>>>> do something
>>>> break if condition
>>>> do something else
>>>>
>>>
>>> It gets worse ;)
>>
>> break if condition
>>
>> Also implies...
>>
>> continue if condition
>>
>
> That's true, why not? I don't use use continue so much but it seems
> logical.
>
>> Never mind
>>
>> break if condition else continue
>> continue if condition else break
>>
>
> No that would be silly.
Why? It follows directly from conditional expressions as well as your
proposed syntax?
>> Because who would want to write...
>> break if condition
>> continue
>>
>> or
>> continue if condition
>> break
>>
>
> The problem is: when would you need to do this? I pointed out in my
> original post that almost half of uses of 'break' in the py3k python source
> come immediately after an 'if'. Now I have never used or seen this:
>
> if condition:
> break
> continue
Just because *you've* never seen it, doesn't mean it shouldn't be a
valid control structure.
while ...:
#do some stuff
if some_condition:
#do some other stuff
break if other_condition else continue
#do yet some other stuff which is skipped by the line above
You are probably thinking; "but Josiah, that secondary clause could be
held in an else clause", and I would confirm that. But then I would
point out that this one example cannot possibly encompass the entirety
of potential uses for the feature.
I would then point out that the cases that you are trying to fix,
'break if condition', you inadvertently hide the *flow control* in a
mass of words. Break and continue are currently happy little
single-word statements. Even when trailing on the same line as an
'if', there is a colon separating them from the if and condition. I
would argue that this punctuation is critical for understanding the
idea "something conditional is happening here to your flow control".
Without that colon, break/continue get to be the only two statements
that get an optional 'if' suffix, whose only purpose seems to be to
reduce line count.
> What would be the point of spelling it 'break if condition else continue'?
> It would even defeat the idea behind my suggestion, which is to make the
> structure of a loop more obvious when you scan code: you can spot the 'break
> if' (and 'continue if'!) statements just by scanning the left hand side of
> the loop body.
But this doesn't help in that. Break and continue are *already*
immediately to the right of whitespace (unless someone tries to make
it a single line), and while the *simple* case of...
for ... in ...:
...
if condition:
break
...
... is common, that doesn't mean that the following isn't ...
for ... in ...:
...
if condition:
...
if other_condition:
break
...
...
Which isn't greatly improved by your suggestion.
>> But if we can break or continue, why not others? What's wrong with a
>> raise (especially if we surround everything with parens...)?
>>
>> (raise Exception("X")) if condition
>>
>> Never mind assert, yield, throw, return, ... I hope this horse is dead
>> now.
>>
>
> You have implied one reason why not: raise, assert, yield, throw, return all
> take an argument which can be an if-expression, so this would make those
> statements difficult to parse if you are human (and I suspect impossible if
> you are the Python parser).
No, I pointed out a syntax that is unambiguous. How do I know it is
unambiguous? Because it's used by the yield *expression* in Python
2.5 and later:
x = (yield y) + 1
Though maybe that's a vote against yield, because the rest are
statements and don't return anything.
> The fact that neither break nor continue take arguments makes them very
> 'poor' in the amount of meaning they convey. That's why a lot of people
> feel like writing the following in one single line.
>
> if condition: break
It's not a question of amount of meaning, it's a question of context.
I've heard explanations at least as much saying that they thought that
not having an indented trailer makes the code "prettier", "shorter",
"easier to understand" as I've heard the opposite from reviewers
arguing against the single-line if idiom.
> Moreover, because we don't have a 'do .. while' construct, 'break' is more
> important than in other languages to shape loops (especially while loops),
> so I thought it would be useful to make it easier to spot. The same
> argument can be made about 'continue' of course.
Perfectly reasonable, but then the base isn't so much...
while 1:
...
if condition: break
...
it's really...
while 1:
...
if condition: break
Which *has* an idiom in Python.
first = 1
while first or condition:
first = 0
...
And before you come back with "but that's not as fast", I'll point out
that an assignment to a local and an or computation are pretty darn
fast. With psyco; even faster:
>>> def test1(n):
... i = 0
... while 1:
... i += 1
... if i >= n: break
...
>>> def test2(n):
... i = 0
... first = 1
... while first or n > i:
... first = 0
... i += 1
...
>>> t = time.time(); test1(10000000); time.time()-t
1.0160000324249268
>>> t = time.time(); test2(10000000); time.time()-t
1.1559998989105225
>>> import psyco
>>> psyco.full()
>>> t = time.time(); test1(1000000000); time.time()-t
1.4059998989105225
>>> t = time.time(); test2(1000000000); time.time()-t
1.4060001373291016
Worst-case, 15% more time without psyco for the *simplest* possible
loop. Less difference as the body of the while increases. With
psyco: no difference.
But what about, "that's not as pretty as 'break if condition'"? Ok,
it's not as pretty. But I would then point out that at least now, you
don't have one of those "while 1:" loops that can raise eyebrows.
- Josiah
More information about the Python-ideas
mailing list