"also" to balance "else" ?

R

Ron Adam

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
 
E

Eloff

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
 
A

Andrew Dalke

Ron said:
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
(e-mail address removed)
 
R

Ron Adam

Eloff said:
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
 
J

John Roth

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
 
R

Ron Adam

John said:
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
 
R

Ron Adam

Andrew said:
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?




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.

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. ;-)

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
(e-mail address removed)

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
 
T

Terry Hancock

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. :-/
 
R

Ron Adam

Terry said:
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
 
F

Fredrik Lundh

praba kar said:
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>
 
D

Donn Cave

Quoth Ron Adam <[email protected]>:
| ... 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, (e-mail address removed)
 
A

Andrew Dalke

Ron said:
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.
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
(e-mail address removed)
 
T

Terry Hancock

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.
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).
 
A

Andrew Dalke

Terry said:
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
(e-mail address removed)
 
F

Fredrik Lundh

Ron said:
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>
 
F

Fredrik Lundh

Terry said:
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>
 
S

Sion Arrowsmith

Fredrik Lundh said:
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.
 
J

John Roth

Andrew Dalke said:
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
 
C

Christos TZOTZIOY Georgiou

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.
 
R

Ron Adam

Sion said:
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
 

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,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top