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

"also" to balance "else" ?

P: n/a

There seems to be a fair amount of discussion concerning flow control
enhancements lately. with, do and dowhile, case, etc... So here's my
flow control suggestion. ;-)
It occurred to me (a few weeks ago while trying to find the best way to
form a if-elif-else block, that on a very general level, an 'also'
statement might be useful. So I was wondering what others would think
of it.

'also' would be the opposite of 'else' in meaning. And in the case of a
for-else... would correct what I believe to be an inconsistency.
Currently the else block in a for loop gets executed if the loop is
completed, which seems backwards to me. I would expect the else to
complete if the loop was broken out of. That seems more constant with
if's else block executing when if's condition is false.
'also' would work like this.

for x in <iteriable>:
BLOCK1
if <condition>: break # do else block
also:
BLOCK2
else:
BLOCK3

where the also block is executed if the loop completes (as the current
else does), and the else block is executed if it doesn't.
while <condition1>:
BLOCK1
if <condition2>: break # jump to else
also:
BLOCK2
else:
BLOCK3

Here if the while loop ends at the while <condition1>, the BLOCK2
executes, or if the break is executed, BLOCK3 executes.
In and if statement...

if <condition1>:
BLOCK1
elif <condition2>:
BLOCK2
elif <condition3>:
BLOCK3
also:
BLOCK4
else:
BLOCK5

Here, the also block would execute if any previous condition is true,
else the else block would execute.
And 'tentatively'<g>, there is the possible 'alif', (also-if), to be
used this way.

if <condition1>:
BLOCK1
alif <condition2>:
BLOCK2
break # skip to also block
alif <condition3>:
BLOCK3
alif <condition4>:
BLOCK4
also: # at lease one condition was true
BLOCK5
else: # no conditions evaluated as true
BLOCK6

Where only one elif will ever evaluate as true, any or all 'alif's could
evaluate as true. This works similar to some case statements except all
alif conditions may be evaluated. Not a true case statement, but a good
replacement where speed isn't the main concern?

I'm not sure if 'elif's and 'alif's could or should be used together?
Maybe a precedence rule would be needed. Or simple that all also's and
alif's must precede any elif's. Then again maybe alif's between elif's
could be useful? For example the alif <condition2> could be and 'elif'
instead, so the break above would't be needed.

'also' can be used without the else in the above examples, and of course
the 'else' doesn't need an 'also'.

I think this gives Pythons general flow control some nice symmetrical
and consistent characteristics that seem very appealing to me. Anyone
agree?

Any reason why this would be a bad idea? Is there an equivalent to an
also in any other language? (I haven't seen it before.)

Changing the for-else is probably a problem... This might be a 3.0 wish
list item because of that.

Is alif too simular to elif?

On the plus side, I think this contributes to the pseudocode character
of Python very well.

Cheers, Ron

Jul 19 '05 #1
Share this Question
Share on Google+
27 Replies


P: n/a
My first reaction was that this is terrible, else clauses on loops are
confusing enough. But if I think about it more, I'm warming up to the
idea. Also/Else for loops is clear, symmetrical, and would be useful.

Reversing the meanign of else will break code, but it's not used that
frequently, and it was a confusing thing to begin with, nothing wrong
in breaking something (slowly!) if it was 'broken' to begin with.

Alifs look evil, I couldn't deduce the control flow very easily, but
then they are a new idea. I'll keep an open mind on that one.

I think the best thing would be to compare the also/else syntax to what
identical functionality looks like in python now [hint to someone with
more time than me right now ;)]. I'd vote for whichever is the more
concise and readable of the two.

-Dan

Jul 19 '05 #2

P: n/a
Ron Adam wrote:
It occurred to me (a few weeks ago while trying to find the best way to
form a if-elif-else block, that on a very general level, an 'also'
statement might be useful. So I was wondering what others would think
of it. for x in <iteriable>:
BLOCK1
if <condition>: break # do else block
also:
BLOCK2
else:
BLOCK3

For this specific case you could rewrite the code in
current Python as

for x in <iterable>:
BLOCK1
if <condition>:
BLOCK3
break
else:
BLOCK2

In order for your proposal to be useful you would need an
example more like the following in current Python

for x in <iterable>:
...
if <condition>:
BLOCK3
break
...
if <condition>:
BLOCK3
break
else:
BLOCK2

That is, where "BLOCK3;break" occurs multiple times in
the loop. My intuition is that that doesn't occur often
enough to need a new syntax to simplify it.

Can you point to some existing code that would be improved
with your also/else?
while <condition1>:
BLOCK1
if <condition2>: break # jump to else
also:
BLOCK2
else:
BLOCK3

Here if the while loop ends at the while <condition1>, the BLOCK2
executes, or if the break is executed, BLOCK3 executes.
which is the same (in current Python) as
while <condition>:
BLOCK1
if <condition2>:
BLOCK3
break
else:
BLOCK2
In and if statement...

if <condition1>:
BLOCK1
elif <condition2>:
BLOCK2
elif <condition3>:
BLOCK3
also:
BLOCK4
else:
BLOCK5

Here, the also block would execute if any previous condition is true,
else the else block would execute.
That is ... funky. When is it useful?

One perhaps hackish solution I've done for the rare cases when
I think your proposal is useful is

while 1:
if <condition1>:
BLOCK1
elif <condition2>:
BLOCK2
elif <condition3>:
BLOCK3
else:
# couldn't do anything
break
BLOCK4
break
I think this gives Pythons general flow control some nice symmetrical
and consistent characteristics that seem very appealing to me. Anyone
agree?


No. Having more ways to do control flow doesn't make for code that's
easy to read.

My usual next step after thinking (or hearing) about a new Python
language change is to look at existing code and see if there's
existing code which would be easier to read/understand and get an
idea if it's a common or rare problem. Perhaps you could point
out a few examples along those lines?

Andrew
da***@dalkescientific.com

Jul 19 '05 #3

P: n/a
Eloff wrote:
My first reaction was that this is terrible, else clauses on loops are
confusing enough. But if I think about it more, I'm warming up to the
idea. Also/Else for loops is clear, symmetrical, and would be useful.

Reversing the meanign of else will break code, but it's not used that
frequently, and it was a confusing thing to begin with, nothing wrong
in breaking something (slowly!) if it was 'broken' to begin with.

Alifs look evil, I couldn't deduce the control flow very easily, but
then they are a new idea. I'll keep an open mind on that one.
Yes, it's probably because it's new. Alifs would be used where you want
to test for multiple possible values, and need to respond differently
depending on the values. They probably wouldn't be used as often as elifs.

alifs is a way to string if's together as a group. The following would
be equivalent to if-alif-also-else.

didif = False
if val == condition1:
didif = True
BLOCK1
if val == condition2:
didif = True
BLOCK2
if val == condition3:
didif = True
if didif:
BLOCK3
else:
BLOCK4
The if-alif-also-else version doesn't need the extra name to mark if any
of the conditions were true.

if val == condition1:
BLOCK1
alif val == condition2:
BLOCK2
alif val == condition3:
BLOCK3
also:
BLOCK4
else:
BLOCK5

But I think we will need to find some real use case's to make it
convincing.

I think the best thing would be to compare the also/else syntax to what
identical functionality looks like in python now [hint to someone with
more time than me right now ;)]. I'd vote for whichever is the more
concise and readable of the two.

-Dan


In cases of if-also, the equivalent code needs an extra local variable
and an additional if statement.

iftest = False
if <condition>:
iftest = True
BLOCK1
elif <condition>:
iftest = True
BLOCK2
if iftest:
BLOCK3

This is the pattern that caused me to think of having an also. I was
parsing and formatting doc strings at the time, and also would allow it
to become.

if <condition>:
BLOCK1
elif <condition>:
BLOCK2
also:
BLOCK3

Which is much easier to read.
Ron
Jul 19 '05 #4

P: n/a

"Ron Adam" <rr*@ronadam.com> wrote in message
news:H6********************@tornado.tampabay.rr.co m...
Currently the else block in a for loop gets executed if the loop is
completed, which seems backwards to me. I would expect the else to
complete if the loop was broken out of. That seems more constant with
if's else block executing when if's condition is false.


Actually, it makes sense if you look at it correctly.

In an unadorned loop, exits via break and via the
loop condition becoming false go to the same place.
To distinguish requires some kind of a switch.

In a loop with an else, exits via break skip the else
clause, while an exit via the loop condition takes
the else clause. You don't need a special exit on
break since you can put any amount of logic after
the if and in front of the break. Where you need it
is on exit via the loop condition.

The difficulty you're having with this is that else
is a very bad keyword for this particular construct.
I'd prefer something like "on normal exit" as
a keyword.

John Roth

Jul 19 '05 #5

P: n/a
John Roth wrote:

"Ron Adam" <rr*@ronadam.com> wrote in message
news:H6********************@tornado.tampabay.rr.co m...
Currently the else block in a for loop gets executed if the loop is
completed, which seems backwards to me. I would expect the else to
complete if the loop was broken out of. That seems more constant with
if's else block executing when if's condition is false.

Actually, it makes sense if you look at it correctly.

In an unadorned loop, exits via break and via the
loop condition becoming false go to the same place.
To distinguish requires some kind of a switch.

In a loop with an else, exits via break skip the else
clause, while an exit via the loop condition takes
the else clause. You don't need a special exit on
break since you can put any amount of logic after
the if and in front of the break. Where you need it
is on exit via the loop condition.

The difficulty you're having with this is that else
is a very bad keyword for this particular construct.
I'd prefer something like "on normal exit" as
a keyword.


It's not a difficulty. This is the point I was making. :)

My suggestion is to use, also as the keyword to mean "on normal exit"
'also' do this.

Ron
Jul 19 '05 #6

P: n/a
On Monday 13 June 2005 11:09 pm, Ron Adam wrote:
John Roth wrote:
"Ron Adam" <rr*@ronadam.com> wrote in message
news:H6********************@tornado.tampabay.rr.co m...
The difficulty you're having with this is that else
is a very bad keyword for this particular construct.
I'd prefer something like "on normal exit" as
a keyword.


It's not a difficulty. This is the point I was making. :)

My suggestion is to use, also as the keyword to mean "on normal exit"
'also' do this.


Unfortunately, "also" is also a bad keyword to use for this, IMHO.
I don't find it any more intuitive than "else". (And since your idea
would break if-else code, I don't think it would be allowed, anyway).

I can't think of what would be a better keyword, though. :-/

--
Terry Hancock ( hancock at anansispaceworks.com )
Anansi Spaceworks http://www.anansispaceworks.com

Jul 19 '05 #7

P: n/a
Andrew Dalke wrote:
Ron Adam wrote:
It occurred to me (a few weeks ago while trying to find the best way to
form a if-elif-else block, that on a very general level, an 'also'
statement might be useful. So I was wondering what others would think
of it.
for x in <iteriable>:
BLOCK1
if <condition>: break # do else block
also:
BLOCK2
else:
BLOCK3


For this specific case you could rewrite the code in
current Python as

for x in <iterable>:
BLOCK1
if <condition>:
BLOCK3
break
else:
BLOCK2


True, but I think this is considerably less clear. The current for-else
is IMHO is reversed to how the else is used in an if statement.

In order for your proposal to be useful you would need an
example more like the following in current Python

for x in <iterable>:
...
if <condition>:
BLOCK3
break
...
if <condition>:
BLOCK3
break
else:
BLOCK2

That is, where "BLOCK3;break" occurs multiple times in
the loop. My intuition is that that doesn't occur often
enough to need a new syntax to simplify it.
I think you have BLOCK 2 and 3 confused here. BLOCK2 is the 'also'
block above. The current for-else already does the 'also' behavior. I'm
asking if changing the current 'else' in a for statement to 'also' would
make it's current behavior clearer. It's been stated before here that
current behavior is confusing.

You are correct that the 'else' behavior could be nested in the if:break
statement. I think the logical non-nested grouping of code in the
for-also-else form is easier to read. The block in the if statement
before the break isn't part of the loop, IMO, being able to move it to
after the loop makes it clear it evaluates after the loop is done.
Can you point to some existing code that would be improved
with your also/else?

while <condition1>:
BLOCK1
if <condition2>: break # jump to else
also:
BLOCK2
else:
BLOCK3

Here if the while loop ends at the while <condition1>, the BLOCK2
executes, or if the break is executed, BLOCK3 executes.

which is the same (in current Python) as
while <condition>:
BLOCK1
if <condition2>:
BLOCK3
break
else:
BLOCK2


Actually, my example above has a problem, it conflicts with the current
while else. Probably the while-also-else should behave the same as an
if-also-else. Maybe more thinking on how the break behaves in relation
to these is needed.

In and if statement...

if <condition1>:
BLOCK1
elif <condition2>:
BLOCK2
elif <condition3>:
BLOCK3
also:
BLOCK4
else:
BLOCK5

Here, the also block would execute if any previous condition is true,
else the else block would execute.

That is ... funky. When is it useful?


Any time you've writen code that repeats a section of code at the end of
all the if/elif statements or sets a variable to check so you can
conditionally execute a block of code after the if for the same purpose.
One perhaps hackish solution I've done for the rare cases when
I think your proposal is useful is

while 1:
if <condition1>:
BLOCK1
elif <condition2>:
BLOCK2
elif <condition3>:
BLOCK3
else:
# couldn't do anything
break
BLOCK4
break

The type of thing I would try to avoid. ;-)

I think this gives Pythons general flow control some nice symmetrical
and consistent characteristics that seem very appealing to me. Anyone
agree?

No. Having more ways to do control flow doesn't make for code that's
easy to read.


I agree that having more ways isn't a reason by it self.

My thinking is that this would be the type of thing that would be used
to argue against more specialized suggestions. ie... No a <fill in
new suggested keyword here> isn't needed because the also-else form
already does that. ;-)

An example of this might be the case statement suggestions which have
some support and even a PEP. The if-alif-also-else works near enough to
a case statement to fulfill that need. 'alif' (also-if) could be
spelled 'case' and maybe that would be clearer as many people are
already familiar with case statements from other languages.

Vetoing a suggestion on grounds of it can be done in another way, is
also not sufficient either as by that reasoning we would still be using
assembly language. So the question I'm asking here is can an inverse to
the 'else' be useful enough to be considered?

My usual next step after thinking (or hearing) about a new Python
language change is to look at existing code and see if there's
existing code which would be easier to read/understand and get an
idea if it's a common or rare problem. Perhaps you could point
out a few examples along those lines?

Andrew
da***@dalkescientific.com


I'll try to find some use case examples tomorrow, it shouldn't be too
hard. It probably isn't the type of thing that going to make huge
differences. But I think it's a fairly common code pattern so shouldn't
be too difficult to find example uses from pythons library.

Regards, Ron

Jul 19 '05 #8

P: n/a
Terry Hancock wrote:
On Monday 13 June 2005 11:09 pm, Ron Adam wrote:
My suggestion is to use, also as the keyword to mean "on normal exit"
'also' do this.

Unfortunately, "also" is also a bad keyword to use for this, IMHO.
I don't find it any more intuitive than "else". (And since your idea
would break if-else code, I don't think it would be allowed, anyway).


Hi Terry,

How would it break the current if-else?
I can't think of what would be a better keyword, though. :-/


Well there's 'not-else' or 'nelse' Ack! Just kidding of course.

Yes, I can't think of anything that has the same meaning that would
work. 'And' would be the English language alternative to "else", but
it's already used of course.
Regards, Ron

Jul 19 '05 #9

P: n/a
"praba kar" wrote:
I have doubt regarding headers in cgi
programming. If I gives "Content-Type:text/plain"
then I try to print html contents. Is right or wrong
after giving content-type: text/plain?


if you expect the HTML contents to appear as HTML, it's wrong.

(some web browsers may display it as HTML even if it's tagged
as something else, but you shouldn't rely on this)

</F>

Jul 19 '05 #10

P: n/a
Quoth Ron Adam <rr*@ronadam.com>:
| ... The current for-else
| is IMHO is reversed to how the else is used in an if statement.

Is that all? As a matter of opinion, this one is fairly simply
an arbitrary choice to assign a positive sense to completion of
the loop predicate. For search loops, for example, it's clearly
a failure - the loop predicate is there to put a bound on the search,
and to reach that bound is to fail.

Whatever, I don't care if you find this compelling. My point
is that rather than a case of intuition driven by subconscious
forces beyond our control, the choice between two ways to take
the boolean sense of a loop control is really based on some
logical premises, which we can reconsider if it's productive
to do so. I prefer this to fantasies about changing the language,
your mileage may vary.

Donn Cave, do**@drizzle.com
Jul 19 '05 #11

P: n/a
On Tuesday 14 June 2005 12:07 am, Ron Adam wrote:
Terry Hancock wrote:
On Monday 13 June 2005 11:09 pm, Ron Adam wrote:
My suggestion is to use, also as the keyword to mean "on normal exit"
'also' do this.

Unfortunately, "also" is also a bad keyword to use for this, IMHO.
I don't find it any more intuitive than "else". (And since your idea
would break if-else code, I don't think it would be allowed, anyway).


How would it break the current if-else?


I meant "for-else". Typo, sorry. The point is though, that there
is a fairly strict rule against breaking old code, AFAICT. Which
makes the issue academic, "for-else" will continue to mean what
it currently does.
I can't think of what would be a better keyword, though. :-/


Well there's 'not-else' or 'nelse' Ack! Just kidding of course.


No, I know what it should be. It should be "finally". It's already
a keyword, and it has a similar meaning w.r.t. "try".

ISTM, that it would have to be a synonym for "else" though to
be accepted on the backwards-compatibility criterion, and
then it would be "more than one way to do it" which breaks
the Zen. ;-)

Personally, though, "for-finally" would make a lot more sense
to me than "for-else" (and I don't have enough "for-else" code
to worry about it breaking).

--
Terry Hancock ( hancock at anansispaceworks.com )
Anansi Spaceworks http://www.anansispaceworks.com

Jul 19 '05 #12

P: n/a
Ron Adam wrote:
True, but I think this is considerably less clear. The current for-else
is IMHO is reversed to how the else is used in an if statement.
As someone else pointed out, that problem could be resolved in
some Python variant by using a different name, like "at end".
Too late for anything before P3K.
I'm asking if changing the current 'else' in a for statement to 'also'
would make it's current behavior clearer. It's been stated before here
that current behavior is confusing.
"It's been stated" is the passive tense. You are one, and I
saw a couple others. But it isn't the same as "many people say
that the current behavior is confusing." If memory serves, I
don't even recall an FAQ on this, while there is a FAQ regarding
the case statement.
You are correct that the 'else' behavior could be nested in the if:break
statement. I think the logical non-nested grouping of code in the
for-also-else form is easier to read. The block in the if statement
before the break isn't part of the loop, IMO, being able to move it to
after the loop makes it clear it evaluates after the loop is done.
There is a tension with code coherency. In my version the code
that occurs a result of the condition is only in one place while
in yours its in two spots.

If all (>1) break statements in the loop have the same post-branch
code then it might make some sense. But as I said, I don't think
it occurs all that often.

Given the Python maxim of
There should be one-- and preferably only one --obvious way to do it.

which of these is the preferred and obvious way?

while f():
print "Hello!"
if g():
break
else:
print "this is a test"
also:
print "this is not a pipe"

-or-

while f():
print "Hello!"
if g():
print "this is a test"
break
else:
print "this is not a pipe"
I prefer the second over the first.

Which of these is preferred?

while f():
print "Hello"
if g():
a = 10
print "world", a
break
if h():
a = 12
print "world",a
break

-or-

while f():
print "Hello"
if g():
a = 10
break
if h():
a = 12
break
else: # your else, not std. python's
print "world", a

The latter is fragile, in some sense. Suppose I added

if hg():
a = 14
print "there"
break

Then I have to change all of the existing code to put the
"else:" block back into the loop.

That for me makes it a big no.
That is ... funky. When is it useful?


Any time you've writen code that repeats a section of code at the end of
all the if/elif statements or sets a variable to check so you can
conditionally execute a block of code after the if for the same purpose.


Let me clarify. When is it useful in real code? Most cases
I can think of have corner cases which treat some paths different
than others.

My thinking is that this would be the type of thing that would be used
to argue against more specialized suggestions. ie... No a <fill in
new suggested keyword here> isn't needed because the also-else form
already does that. ;-)
An argument for 'X' because it prevents people from asking for
some theoretical 'Y' isn't that strong. Otherwise Python would
have had a goto years ago.
An example of this might be the case statement suggestions which have
some support and even a PEP. The if-alif-also-else works near enough to
a case statement to fulfill that need. 'alif' (also-if) could be
spelled 'case' and maybe that would be clearer as many people are
already familiar with case statements from other languages.
Assuming you are talking about PEP 275 ("Switching on Multiple
Values"), how does this fulfill that need any better than the
existing if/elif/else chain?
Vetoing a suggestion on grounds of it can be done in another way, is
also not sufficient either as by that reasoning we would still be using
assembly language. So the question I'm asking here is can an inverse to
the 'else' be useful enough to be considered?
I disagree. Given the "one -- and preferably only one -- obvious
way to do it" there is already a strong bias against language
features which exist only to do something another way but not
a notably better way.
I'll try to find some use case examples tomorrow, it shouldn't be too
hard. It probably isn't the type of thing that going to make huge
differences. But I think it's a fairly common code pattern so shouldn't
be too difficult to find example uses from pythons library.


My guess is that it will be be hard. There's no easy pattern
to grep for and I don't think the use case you mention comes up
often, much less often enough to need another control mechanism.

Andrew
da***@dalkescientific.com

Jul 19 '05 #13

P: n/a
Terry Hancock wrote:
No, I know what it should be. It should be "finally". It's already
a keyword, and it has a similar meaning w.r.t. "try".


Except that a finally block is executed with normal and exceptional
exit, while in this case you would have 'finally' only called
when the loop exited without a break.

Andrew
da***@dalkescientific.com

Jul 19 '05 #14

P: n/a
Ron Adam wrote:
True, but I think this is considerably less clear. The current for-else
is IMHO is reversed to how the else is used in an if statement.


nope. else works in exactly the same way for all statements that
support it: if the controlling expression is false, run the else suite
and leave the statement.

</F>

Jul 19 '05 #15

P: n/a
Terry Hancock wrote:
Personally, though, "for-finally" would make a lot more sense
to me than "for-else" (and I don't have enough "for-else" code
to worry about it breaking).


"finally" means "run this piece of code no matter what happens in
the previous block". that's not how "else" works in today's Python.

</F>

Jul 19 '05 #16

P: n/a
Fredrik Lundh <fr*****@pythonware.com> wrote:
Ron Adam wrote:
True, but I think this is considerably less clear. The current for-else
is IMHO is reversed to how the else is used in an if statement.

nope. else works in exactly the same way for all statements that
support it: if the controlling expression is false, run the else suite
and leave the statement.


For example, consider the behaviour of:

condition = False
if condition:
print "true"
else:
print "false"

and

condition = False
while condition:
print "true"
break
else:
print "false"

From this, it's clear that while/else gets its semantics from if/else.
Then:

i = 0
while i < 10:
print i
i += 1
else:
print "Done!"

for i in range(10):
print i
else:
print "Done!"

So for/else behaves while/else, hence for/else really is the same way
round as if/else. It may not be "intuitive", but it's consistent, and
personally I'd rather have that.

--
\S -- si***@chiark.greenend.org.uk -- http://www.chaos.org.uk/~sion/
___ | "Frankly I have no feelings towards penguins one way or the other"
\X/ | -- Arthur C. Clarke
her nu becomež se bera eadward ofdun hlęddre heafdes bęce bump bump bump
Jul 19 '05 #17

P: n/a

"Andrew Dalke" <da***@dalkescientific.com> wrote in message
news:pa****************************@dalkescientifi c.com...
Ron Adam wrote:
True, but I think this is considerably less clear. The current for-else
is IMHO is reversed to how the else is used in an if statement.
As someone else pointed out, that problem could be resolved in
some Python variant by using a different name, like "at end".
Too late for anything before P3K.


I don't think it has to wait. There seems to be a movement toward
putting new things in the next couple of releases, and then waiting until
3.0 to remove the old way of doing things.

So "at end" or "on normal exit" could be put in any time;
the use of "else" in that context wouldn't go away until 3.0.
The real question is whether it's worth doing at all. I consider
it a fairly minor issue, all told.

John Roth



Andrew
da***@dalkescientific.com


Jul 19 '05 #18

P: n/a
On Tue, 14 Jun 2005 07:20:06 GMT, rumours say that Andrew Dalke
<da***@dalkescientific.com> might have written:
Given the Python maxim of
There should be one-- and preferably only one --obvious way to do it.

which of these is the preferred and obvious way?

while f():
print "Hello!"
if g():
break
else:
print "this is a test"
also:
print "this is not a pipe"

-or-

while f():
print "Hello!"
if g():
print "this is a test"
break
else:
print "this is not a pipe" I prefer the second over the first.


I am not advocating for either side AFA python 2 is concerned (however I
would substitute "then" for "also"), however the second way does not
handle /elegantly/ multiple break points.

I'm +1 for making "else" the target for break in Py3K though, given an
elegant "also"/"then" keyword.
--
TZOTZIOY, I speak England very best.
"Be strict when sending and tolerant when receiving." (from RFC1958)
I really should keep that in mind when talking with people, actually...
Jul 19 '05 #19

P: n/a
Sion Arrowsmith wrote:
Fredrik Lundh <fr*****@pythonware.com> wrote:

nope. else works in exactly the same way for all statements that
support it: if the controlling expression is false, run the else suite
and leave the statement.

For example, consider the behaviour of:

condition = False
if condition:
print "true"
else:
print "false"

and

condition = False
while condition:
print "true"
break
else:
print "false"

From this, it's clear that while/else gets its semantics from if/else.
Then:

i = 0
while i < 10:
print i
i += 1
else:
print "Done!"

for i in range(10):
print i
else:
print "Done!"

So for/else behaves while/else, hence for/else really is the same way
round as if/else. It may not be "intuitive", but it's consistent, and
personally I'd rather have that.


Thanks Fredric and Sion.

That makes it clearer. So for's else is not dependent on entering the
loop at all.

I'm trying to understand just why it is not intuitive in the first place.

In an if-else, if the if-block executes, the else-block will not
execute. So the else block is the *abnormal* or counter result of the
if condition.

So the (my) confusion comes from the tendency to look at it in terms of
overall program flow rather than in terms of the specific conditional
logic.

In a for loop the normal, as in terminating normally, behavior of a loop
is one where the loop test evaluates as 'False' ending the loop. And
the abnormal or counter behavior is when a break statement executes.
Thus the 'else' block is the normal result, and the skipping the 'else'
block becomes the abnormal counter behavior.

So while the logic is consistent, the expected context is reversed.

Why is else needed in loops? I was working from the point of view that
if there was enough reason for the else to be in loops, and possibly the
same reasoning would apply to an also or counter else. But maybe else
shouldn't be part of the loop to start with?

Regards, Ron







Jul 19 '05 #20

P: n/a
Andrew Dalke wrote:
As someone else pointed out, that problem could be resolved in
some Python variant by using a different name, like "at end".
Too late for anything before P3K.


It was pointed out to me the logic of the else is consistant with the if
in reguard to the loop test it self, it's just when you apply it to the
loop as a whole, the resulting expected code flow becomes counter
intuitive. So it's isn't so much of a problem as it is a gotcha, or
something that has the potential to be a gotcha.

I was thinking that changing the else to an also, would be a small
change, but because I miss understood just what it was testing for. It
would not be correct to change it.

Maybe just removing it from python 3k would be the better choice?

Adding a seperate loop enter/exit test to determine if a loop was exited
with break after it has started, would be a seperate issue and one that
would need more support than the smaller change I was thinking it would
require.

That is ... funky. When is it useful?


Any time you've writen code that repeats a section of code at the end of
all the if/elif statements or sets a variable to check so you can
conditionally execute a block of code after the if for the same purpose.


Let me clarify. When is it useful in real code? Most cases
I can think of have corner cases which treat some paths different
than others.


Here are some examples that I've found from the libary where the program
flow matches the if-elif-also logic but was writen differntly.
#from urllib.py
def redirect_internal(self, url, fp, errcode, errmsg, headers, data):
if 'location' in headers:
newurl = headers['location']
elif 'uri' in headers:
newurl = headers['uri']
else:
return
void = fp.read()
fp.close()
# In case the server sent a relative URL, join with original:
newurl = basejoin(self.type + ":" + url, newurl)
return self.open(newurl)
#could be...
def redirect_internal(self, url, fp, errcode, errmsg, headers, data):
if 'location' in headers:
newurl = headers['location']
elif 'uri' in headers:
newurl = headers['uri']
also:
void = fp.read()
fp.close()
# In case the server sent a relative URL,
# join with original:
newurl = basejoin(self.type + ":" + url, newurl)
return self.open(newurl)

#from difflib.py
tag = ''
if i < ai and j < bj:
tag = 'replace'
elif i < ai:
tag = 'delete'
elif j < bj:
tag = 'insert'
if tag:
answer.append( (tag, i, ai, j, bj) )

#could be...
if i < ai and j < bj:
tag = 'replace'
elif i < ai:
tag = 'delete'
elif j < bj:
tag = 'insert'
also:
answer.append( (tag, i, ai, j, bj) )

This one is simular to the code I was writing when I want'ed to use an
inverse else. It doesn't require 'tag' to be initialized before hand.
# from imputil.py
class BuiltinImporter(Importer):
def get_code(self, parent, modname, fqname):
if parent:
# these modules definitely do not occur within a package
context
return None

# look for the module
if imp.is_builtin(modname):
type = imp.C_BUILTIN
elif imp.is_frozen(modname):
type = imp.PY_FROZEN
else:
# not found
return None

# got it. now load and return it.
module = imp.load_module(modname, None, modname, ('', '', type))
return 0, module, { }

#could be...
class BuiltinImporter(Importer):
def get_code(self, parent, modname, fqname):
if parent:
# these modules definitely do not occur
# within a package context
return None

# look for the module
if imp.is_builtin(modname):
type = imp.C_BUILTIN
elif imp.is_frozen(modname):
type = imp.PY_FROZEN
also:
# got it. now load and return it.
module = imp.load_module(modname, None, modname, \
('', '', type))
return 0, module, { }

# not found
# return None
None of these are big or dramatic changes of the sort that I couldn't
live without. Finding examples in the library is more difficult than I
expected, so while this seems like a good idea... I'm not convinced yet
either. But that is why I posted is to find out what other thought.

Regurds, Ron

Jul 19 '05 #21

P: n/a
Ron Adam wrote:
So the (my) confusion comes from the tendency to look at it in terms of
overall program flow rather than in terms of the specific conditional
logic.

In a for loop the normal, as in terminating normally, behavior of a loop
is one where the loop test evaluates as 'False' ending the loop. And
the abnormal or counter behavior is when a break statement executes.
Thus the 'else' block is the normal result, and the skipping the 'else'
block becomes the abnormal counter behavior.


a typical use-case for for-in-else is a search loop:

for item in collection:
if predicate(item):
print "found", item
break
else:
print "not found"
return

print "use", item

where your "abnormal behaviour" is, of course, the expected
behaviour. if you insist on looking at things the wrong way,
things will look reversed.

</F>

Jul 19 '05 #22

P: n/a
On Wednesday 15 June 2005 03:57 am, Fredrik Lundh wrote:
where your "abnormal behaviour" is, of course, the expected
behaviour. if you insist on looking at things the wrong way,
things will look reversed.


Unfortunately, the converse is true, too: no matter how twisted
an idea is, you can make it seem logical with the right point
of view. ;-)

I think the OP is correct in saying that for-else is non-intuitive.

Your use case is the only one in which "else" makes sense, IMHO,
and that's only because it reflects the overall meaning of the
algorithm, not because it actually reflects what's going on in
the syntax.

If "finally" is wrong (and I see your point there), then maybe
"normally" is the right thing to call it? After all, it's the opposite
of the "exception" case, which is probably the "normal" case.

The fact that, in a search algorithm, the exception case is the
normal result, and the syntactically normal case is the exception
just confuses the issue. The question is, how difficult is it for
the person reading the code to understand what was written?

Now of course, a person skilled in language X will understand
the syntax even if all the keywords are unintelligible
gibberish, and from that PoV, it will surely make sense. But
I get the impression that Python is *trying* to use words with
the right inuitive meaning in the interest of helping newbies.

I *personally* can get my head around "for-else" and use it
if I really need it, but I agree that it could be spelled better.

OTOH, I see no reason for an opposite construct, since, as you
and others have pointed out, that can be handled by the if
in the loop or by an exception handler.

--
Terry Hancock ( hancock at anansispaceworks.com )
Anansi Spaceworks http://www.anansispaceworks.com

Jul 19 '05 #23

P: n/a
Fredrik Lundh wrote:
Ron Adam wrote:

So the (my) confusion comes from the tendency to look at it in terms of
overall program flow rather than in terms of the specific conditional
logic.

In a for loop the normal, as in terminating normally, behavior of a loop
is one where the loop test evaluates as 'False' ending the loop. And
the abnormal or counter behavior is when a break statement executes.
Thus the 'else' block is the normal result, and the skipping the 'else'
block becomes the abnormal counter behavior.

a typical use-case for for-in-else is a search loop:

for item in collection:
if predicate(item):
print "found", item
break
else:
print "not found"
return

print "use", item

where your "abnormal behaviour" is, of course, the expected
behaviour. if you insist on looking at things the wrong way,
things will look reversed.

</F>


It isn't so much as reading it the wrong way, as it is to how it reads
in the context it is used in. In the above it works out that the
negative search result is a successful loop completion, so the else
reads correctly in that context.

If the context was one of verifying completeness or correctness of a
collection, then the context would be reversed and the else would
indicate success instead of failure.

I do see it both ways. Testing for an item in a list is probably the
more common occurrence.

If anything, this just points out the error of trying to apply code
logic to a larger context. They aren't always the same. It is nice when
code logic matches the context it's used in, as it makes the code much
easier to read and understand.

My initial thought of adding 'also' was that it might lead to being able
to write more code where the code logic more directly parallels the
context it's used in. From the few example uses I've found in the
library, it looks like it wouldn't make that big of a difference.

Maybe someone else can find more uses than I have. <shrug> I tried.

Regards, Ron

Jul 19 '05 #24

P: n/a
Ron Adam wrote:
It occurred to me (a few weeks ago while trying to find the best way to
form a if-elif-else block, that on a very general level, an 'also'
statement might be useful. So I was wondering what others would think
of it.


But the feature is already there:

for x in <iterable>:
BLOCK1
if <condition>:
ALSO-BLOCK
break
else:
BLOCK2

If find "else" fine, since the only times I used it is in searches:

for x in <iterable>
BLOCK1
if <gotcha-condition>: break
else:
raise Exception('Not found')

In that case, 'else' sounds like the good keyword.

Regards,
Nicolas
Jul 19 '05 #25

P: n/a
Terry Hancock wrote:
On Wednesday 15 June 2005 03:57 am, Fredrik Lundh wrote:
where your "abnormal behaviour" is, of course, the expected
behaviour. if you insist on looking at things the wrong way,
things will look reversed.


Unfortunately, the converse is true, too: no matter how twisted
an idea is, you can make it seem logical with the right point
of view. ;-)

I think the OP is correct in saying that for-else is non-intuitive.


Although it took me a while to verbalize it, My motivation for
suggesting 'also' was/is that it might enable writing code that better
matches the context it's written in. Code that's more intuitive and as
a result more readable.

There are 4 possible outcomes to a loop.

1. Not Entered. Nothing done. (current possible for-else behavior)

2. Entered. Some loops may have completed.

3. Not finished. (break) Some loops may have completed.

4. Finished (no break) All possible loops completed.
(current for-else behavior)

(This doesn't include exit by return statements.)
One possibility may be to use a keyword that parallels the except in
try-except blocks which will accept a test designator. (building on your
refernce to finally)

(This is probably a definite after 3k item I think, or more likely just
academic discussion, but I enjoy that too.)

So use loop as the new keyword with the above conditions and have the
else as the alternative to any of them.

(Feel free to suggest different words)
for item in collection:
if <condition>:
print "item found"
break
loop Finished:
print "item was not found."
return
for item in collection:
if <condition>:
print "bad item"
break
loop Finished:
print "The Collection pass's the test"
else:
print "The Collection is invalid"
for item in collection:
<do something>
loop NotEntred:
print "The Collection was empty"
for line in textbuffer:
print line
loop Entered:
print time.date()
else:
print "The buffer was empty"
while <condition>:
<do something>
if <condition>:
break
loop Entered:
<do something>
I think these are sufficiently explicit as to avoid being non-intuitive.
The endloop might be generalized into a endblock or endsuite statement
possibly. I'm not sure if that would have any uses's in the proposed
"with" statements or not. (?)

Regards,
Ron

Jul 19 '05 #26

P: n/a
Nicolas Fleury wrote:
Ron Adam wrote:
It occurred to me (a few weeks ago while trying to find the best way
to form a if-elif-else block, that on a very general level, an 'also'
statement might be useful. So I was wondering what others would think
of it.


But the feature is already there:


Yes, that was pointed out to me, I was first interested in it as an
if-also, which I found a few uses for and thought that it might
naturally be extended to for and while, but the interpretation of the
else in for loops conflicts with it, so it's ruled out in that form.
See the last message I posted in this thread for a more explicit
alternative that is more flexible and have less of a tenancy to be
counter intuitive. Although a bigger change overall.

I don't expect too much support for that one either, but who knows. The
conversation is interesting (to me). ;-)

Cheers,
Ron

Jul 19 '05 #27

P: n/a
Nicolas Fleury <ni******@yahoo.com_remove_the_> wrote:

But the feature is already there:

for x in <iterable>:
BLOCK1
if <condition>:
ALSO-BLOCK
break
else:
BLOCK2


I've been using Python for 8 years. I never knew that feature was in
there.
--
- Tim Roberts, ti**@probo.com
Providenza & Boekelheide, Inc.
Jul 19 '05 #28

This discussion thread is closed

Replies have been disabled for this discussion.