Hi,
this is my first message to this list, so let me say hello first.
I want to ask what you think about introducing a keyword 'eltry' which would be the counterpart of 'elif' for try statements. This had been suggested before on python-list a couple of years ago by Jonathan Gardner, but nothing (that I could find) seems to have come of it.
Starting from PEP 341, the try statement might be extended to
try_stmt: 'try' ':' suite ( (except_clause ':' suite)+ ( 'eltry' ':' suite (except_clause ':' suite)+ )* ['else' ':' suite] ['finally' ':' suite] | 'finally' ':' suite )
where lines 4 through 7 would be an addition to the definition given in the PEP. Admittedly, this looks somewhat complex, but I don't think it actually is. (And while an new keyword always means potentially breaking code, 'eltry' doesn't seem to me a likely identifier chosen by programmers - YMMV.)
This extension would be useful whenever a suite of statements is to be terminated as soon as one of them raises an exception, and the programmer is interested in handling those individually. Without 'eltry' the choices are:
- Stack conventional try statements, each inside the else clause of the one before. This causes deep nesting, and while typical nesting depths won't be as great as they might become with stacked if statements, it is annoying and ugly IMO.
- Run all statements at once and put all exception handlers outside the suite. This yields code that is harder to read than necessary as some handlers will be written far from the statement where the exception they handle is raised. Moreover, if more than one statement may raise a particular exception, some effort is required to find out which one did it if there is only one handler for that exception.
- Break up the suite into separate try statements. While this may result in well readable code if each handler breaks out of the block containing the whole run of try statements, it requires some mechanism (such as a wrapper try statement or a separate function that may quit anytime) if exiting the current block is not desired.
- Something else, in which case I'm looking forward to learning something new about Python ;o)
An example would be a filter chain:
def use_eltry(data): # decode as far as possible try: data = foo_decode(data) except ValueError: print "Data seems not to be foo encoded." eltry: data = bar_decode(data) except ValueError: print "Foo decoded data seems not to be bar encoded." eltry: data = baz_decode(data) except ValueError: print "FooBar decoded data seems not to be baz encoded."
# whatever data is by now, do something with it do_something(data)
def use_stacking(data): # decode as far as possible try: data = foo_decode(data) except ValueError: print "Data seems not to be foo encoded." else: try: data = bar_decode(data) except ValueError: print "Foo decoded data seems not to be bar encoded." else: try: data = baz_decode(data) except ValueError: print "FooBar decoded data seems not to be baz encoded."
# whatever data is by now, do something with it do_something(data)
def use_single_handler(data): # decode as far as possible try: data = foo_decode(data) data = bar_decode(data) data = baz_decode(data) except ValueError: print "Data could not be decoded, can't tell you why easily."
# whatever data is by now, do something with it do_something(data)
def use_custom_exception(data): # decode as far as possible try: try: data = foo_decode(data) except ValueError: print "Data seems not to be foo encoded." raise
try: data = bar_decode(data) except ValueError: print "Foo decoded data seems not to be bar encoded." raise
try: data = baz_decode(data) except ValueError: print "FooBar decoded data seems not to be baz encoded." raise except ValueError: pass
# whatever data is by now, do something with it do_something(data)
def use_function(data): # decode as far as possible def helper(): try: data = foo_decode(data) except ValueError: print "Data seems not to be foo encoded." return
try: data = bar_decode(data) except ValueError: print "Foo decoded data seems not to be bar encoded." return
try: data = baz_decode(data) except ValueError: print "FooBar decoded data seems not to be baz encoded." return
helper()
# whatever data is by now, do something with it do_something(data)
Does this seem contrived? (Obviously, I don't think so.) It would be nice to hear your opinions and, if you don't agree with the proposal, learn what is bad about it.
On 7/6/05, Thomas Lotze thomas@thomas-lotze.de wrote:
I want to ask what you think about introducing a keyword 'eltry' which would be the counterpart of 'elif' for try statements. This had been suggested before on python-list a couple of years ago by Jonathan Gardner, but nothing (that I could find) seems to have come of it.
I'm -1 on this. The use case doesn't occur often in my experience and IMO putting each try statement in the else clause of the previous one is a fine solution.
I also notice that your only example is very repetitive, and would be better written as a loop, using Python's dynamic nature:
for decoder in foo_decode, bar_decode, foobar_decode: try: data = decoder(data) break except ValueError: print "data doesn't seem to be %s-encoded" % decoder.__name__
[Thomas Lotze]
I want to ask what you think about introducing a keyword 'eltry' which would be the counterpart of 'elif' for try statements. This had been suggested before on python-list a couple of years ago by Jonathan Gardner, but nothing (that I could find) seems to have come
of it.
[Guido]
I'm -1 on this. The use case doesn't occur often in my experience and IMO putting each try statement in the else clause of the previous one is a fine solution.
I also notice that your only example is very repetitive, and would be better written as a loop, using Python's dynamic nature:
for decoder in foo_decode, bar_decode, foobar_decode: try: data = decoder(data) break except ValueError: print "data doesn't seem to be %s-encoded" % decoder.__name__
FWIW, the looping solution has worked out well in practice. From csv.py:
for thisType in [int, long, float, complex]: try: thisType(row[col]) break except (ValueError, OverflowError): pass
Raymond
Guido van Rossum gvanrossum@gmail.com wrote:
I also notice that your only example is very repetitive, and would be better written as a loop, using Python's dynamic nature:
Sure, that's true for the example given. Getting other stuff into a form which allows for looping may require additional code.
But then, the example was intended to illustrate, not persuade. It's fine with me if you're determined that eltry is a bad (or at least not good enough) idea. I do wish for it occasionally, but that's true for a number of things.
Thinking about it some more, I find that a symmetry between statements which have an 'else' part would be appealing from an aesthetic point of view, which includes introduction of 'elfor' and 'elwhile' - or allowing for syntax like 'else if ...:' and 'else try:'. (It seems some people favour that anyway. OTOH, I undestand that introducing two-token constructs doesn't necessarily simplify parsing.) But I haven't encountered any use cases for that, so it's probably just idle musing.
On 7/7/05, Thomas Lotze thomas@thomas-lotze.de wrote:
Sure, that's true for the example given. Getting other stuff into a form which allows for looping may require additional code.
Well, hypothetical illustrations don't carry much value when arguing for something as substantial as new syntax requiring a new keyword. You have to present an actual use case with an indication (even if only anecdotal) of how common the use case is, and an explanation why the existing ways of handling that use case are inadequate.
Your illustration doesn't count as a use case because it is easily handled already.
Thinking about it some more, I find that a symmetry between statements which have an 'else' part would be appealing from an aesthetic point of view, which includes introduction of 'elfor' and 'elwhile' - or allowing for syntax like 'else if ...:' and 'else try:'. (It seems some people favour that anyway. OTOH, I undestand that introducing two-token constructs doesn't necessarily simplify parsing.) But I haven't encountered any use cases for that, so it's probably just idle musing.
The parsing would be easy enough (and in fact I sometimes think it was a mistake to introduce elif just to save typing "else if".
The problem with the elwhile/elfor/eltry idea (apart from the explosion of new keywords) is that you're just as likely to need e.g. a "try" in the else clause of a while-loop as another while, so you'd end up having all combinations in the syntax. Since, as you say, the use cases are rare, the syntactic complexity isn't worth it.
I even wonder if else-clauses on for/while were a good idea. (The one on try is definitely a good idea since the use case is quite frequent and only clumsily handled otherwise; the use cases for else on for/while are less convincing IMO.)
[Guido van Rossum]
I even wonder if else-clauses on for/while were a good idea.
I surely find them useful, and see them as a Python originality (a welcome one).
On 7/7/05, François Pinard pinard@iro.umontreal.ca wrote:
[Guido van Rossum]
I even wonder if else-clauses on for/while were a good idea.
I surely find them useful, and see them as a Python originality (a welcome one).
They are indeed an original invention. (One day I looked at the similarity between if and while and noticed that there was a use case for else after while too.)
The question remains whether Python would be easier to learn without them. And if so, the question would remain whether that's offset by their utility for experienced developers. All hard to assess impartially!
Guido van Rossum gvanrossum@gmail.com wrote:
On 7/7/05, François Pinard pinard@iro.umontreal.ca wrote:
[Guido van Rossum]
I even wonder if else-clauses on for/while were a good idea.
I surely find them useful, and see them as a Python originality (a welcome one).
They are indeed an original invention. (One day I looked at the similarity between if and while and noticed that there was a use case for else after while too.)
The question remains whether Python would be easier to learn without them. And if so, the question would remain whether that's offset by their utility for experienced developers. All hard to assess impartially!
(data point)
I had gotten along for 5 years without knowing/remembering there existed an else clause in for and while loops until the beginnings of the thunk/block/with discussion in February or March. Commercial work puts me at around 30k lines of Python in the last year. In the last 3-4 months, I've used the else clause on for and while around 5 times.
In looking at the tutorial, I notice that else clauses on loops is discussed a few sections after discussion on the loops themselves. This seems like a reasonable location to me, though to be sure, we should find some people, get them to learn Python through the tutorial, then ask them what they thought of the tutorial on else clauses in for and while loops, and whether or not they confused them.
- Josiah
[Josiah Carlson]
[Guido van Rossum]
I even wonder if else-clauses on for/while were a good idea.
I had gotten along for 5 years without knowing/remembering there existed an else clause [...]
Just throwing a few more cents in. I have been programming (rather successfully) for a few dozens of years without such `else:' clauses, and for example, nearly as long without integrated object orientation. Such things are not mandatory: we all know how to manage without them. It is just that, when such features are known and available, they alleviate programming work, sometimes a bit, sometimes more, depending.
Similarly, for anyone reasonable, there is no real urge nor fundamental necessity (bugs excepted) going from Python 2.0 to 2.4. We may undoubtedly enjoy new features once they happen to be there, but could well continue to live a successful programming life without them. `else:' falls in this category. It is nice and helpful to have, but is only one of the now numerous features of Python which are not essential.
The fact that we can go without knowing something does not mean that this something is not welcome. Some priests do not know sex! :-)
[Guido, on {for,while}/else] ...
The question remains whether Python would be easier to learn without them. And if so, the question would remain whether that's offset by their utility for experienced developers. All hard to assess impartially!
That's what I'm here for. I like loop "else" clauses, but have to admit that (a) I rarely use them; (b) most of the time I use them, my control flow is on the way to becoming so convoluted that I'm going to rewrite the whole function soon anyway; and, (c) I've often misread code that uses them, mentally attaching the "else" to a nearby "if" instead.
I also suspect that if they weren't in the language already, a PEP to introduce them would fail, because
still_looking = True some loop: if found it: still_looking = False break if still_looking: # what would have been in the "else" clause
is clear and easy to write without it.
[Guido, on {for,while}/else] ...
The question remains whether Python would be easier to learn without them. And if so, the question would remain whether that's offset by their utility for experienced developers. All hard to assess impartially!
[Tim saves the day]
That's what I'm here for. I like loop "else" clauses, but have to admit that (a) I rarely use them; (b) most of the time I use them, my control flow is on the way to becoming so convoluted that I'm going to rewrite the whole function soon anyway; and, (c) I've often misread code that uses them, mentally attaching the "else" to a nearby "if" instead.
I also suspect that if they weren't in the language already, a PEP to introduce them would fail, because
still_looking = True some loop: if found it: still_looking = False break if still_looking: # what would have been in the "else" clause
is clear and easy to write without it.
OTOH I don't particularly like code that requires flag variables; they often make me squirm because the same condition (flag) is tested multiple times where it could be tested just once if more sophisticated flow control (e.g. an else clause :) was available.
How would a PEP to *remove* this feature fare today?
Unhelpfully,
On Thu, Jul 07, 2005, Guido van Rossum wrote:
OTOH I don't particularly like code that requires flag variables; they often make me squirm because the same condition (flag) is tested multiple times where it could be tested just once if more sophisticated flow control (e.g. an else clause :) was available.
That's what I use try/except for. ;-)
[Guido]
OTOH I don't particularly like code that requires flag variables;
Me neither; that's indeed why this one isn't a slam dunk.
they often make me squirm because the same condition (flag) is tested multiple times where it could be tested just once if more sophisticated flow control (e.g. an else clause :) was available.
What burns me (far) more often in practice is "simulating" a multi-level `break` or `continue`. Then multiple flag variables get introduced, set, and tested multiple times at multiple "logical indent levels" too. That can also be viewed as stemming from a lack of more sophisticated flow control. One-loop found-it-or-didn't kinds of flag variables have spatial locality that makes them (IME) quite easy to live with, in comparison.
How would a PEP to *remove* this feature fare today?
Easy: it would be rejected, but with a note that it should be reconsidered for Python 3000.
Unhelpfully,
your-opposite-in-oh-so-many-ways<wink>-ly y'rs - tim
On 7/7/05, Tim Peters tim.peters@gmail.com wrote:
[Guido]
OTOH I don't particularly like code that requires flag variables;
Me neither; that's indeed why this one isn't a slam dunk.
they often make me squirm because the same condition (flag) is tested multiple times where it could be tested just once if more sophisticated flow control (e.g. an else clause :) was available.
What burns me (far) more often in practice is "simulating" a multi-level `break` or `continue`. Then multiple flag variables get introduced, set, and tested multiple times at multiple "logical indent levels" too. That can also be viewed as stemming from a lack of more sophisticated flow control. One-loop found-it-or-didn't kinds of flag variables have spatial locality that makes them (IME) quite easy to live with, in comparison.
How would a PEP to *remove* this feature fare today?
Easy: it would be rejected, but with a note that it should be reconsidered for Python 3000.
Barry also reiterated this idea and I support removing them in Python 3000. I do use them when I want to know when I break out of a loop prematurely, but I am definitely not a typical use case for experienced users since I basically learned how to program in Python so I didn't have any baggage preventing me from not remembering they existed.
Simplifying the basic control flow mechanisms is always good. And as Aahz pointed out, you can use exceptions to break out of a loop easily enough and have code for only when you break out with the exception (maybe we should add a ControlFlowException in Py3000 that all other control flow exceptions, like StopIteration inherit from?). In other words they are not critical and not used frequently from what it sounds like. And even in the cases where they are used they can be reworked to not need them without much hassle.
-Brett
How would a PEP to *remove* this feature fare today?
I hope not well, since I use them quite often.
Barry also reiterated this idea and I support removing them in Python 3000. I do use them when I want to know when I break out of a loop prematurely, but I am definitely not a typical use case for experienced users since I basically learned how to program in Python so I didn't have any baggage preventing me from not remembering they existed.
So you're indeed an example that learning them might not be an issue, even when no previous programming experience exists.
For the case of an experienced programmer getting into Python as a new language, most of us have been there, and I remember that, when I understood what it was about, I was actually amazed rather than confused. I started wondering why it's not available in other languages.
Simplifying the basic control flow mechanisms is always good.
[...]
Of course, it largely depends on what simplifying means to you.
As a side comment, I belive that talking often and at regular intervals about builtins and syntax which may disappear from the language in the next major version is not something good.
I understand that the next major is being seen as the place to break legacy compatibility, but that's the kind of thing that you (Guido) are aware that no comments besides personal likes and dislikes will be raised. If you *really* want to remove them (even though I strongly dislike the idea ;-), decide it and get just half of the complaints, rather than getting all of them and spreading FUD.
On 7/7/05, Gustavo Niemeyer gustavo@niemeyer.net wrote:
Simplifying the basic control flow mechanisms is always good.
[...]
Of course, it largely depends on what simplifying means to you.
If we lose the "else" in "for"s, we'd have to use a variable to mark when we exit the normal way or we break it out.
Using another variable is something that complicates the reading of the program: you see the new variable, have to discover to what it's for, and to keep it in your mind while you follow the logic.
For me, simplifying means keeping the "else".
Just my Currency("0.02"), ;)
. Facundo
Blog: http://www.taniquetil.com.ar/plog/ PyAr: http://www.python.org/ar/
On Thu, 2005-07-07 at 14:54, Guido van Rossum wrote:
How would a PEP to *remove* this feature fare today?
Not well, I hope, although I suppose everything's up for debate in Py3K.
Yes, they're rarely used and there is an alternative, but I do find them useful and succinct when they're needed. Also, I don't think they're really much of a burden on newbies because mostly, they just don't encounter them or need to know about them.
-Barry
[Guido, on {for,while}/else]
How would a PEP to *remove* this feature fare today?
-1.
It took me a while (actually a *long* while) to start using else clauses in loops, but I've learned to love them. Although there aren't that many use cases, they make the code more readable (and writable) where they apply.
For me, for/else and while/else didn't make Python harder to learn; I just ignored them for some years.
And I'm horrified at the thought of having to go look for all occurrences if they were removed (if Py3k ever happens, I'd hope that it would be the *one* Python to use -- too many incompatibilities would probably mean *two* Pythons fighting each other).
tanzer@swing.co.at wrote:
... if Py3k ever happens, I'd hope that it would be the *one* Python to use -- too many incompatibilities would probably mean *two* Pythons fighting each other).
A caduceus to heal software problems?
http://www.pantheon.org/articles/c/caduceus.html
--Scott David Daniels Scott.Daniels@Acm.Org
On Friday 08 July 2005 04:54, Guido van Rossum wrote:
How would a PEP to *remove* this feature fare today?
I'd very much prefer that we kept them. I find it a useful way to group the behaviour of the looping - this bit is the normal loop, and this bit at the end is when the loop fails/is exhausted. This is obviously for when you use it in a loop where you're looking for a certain result. And yes, you can do something similar with try/except, but I find that ugly - 'break' is the natural way to get out of a loop, not 'raise'. I find using exceptions in this way to be a sort of horrible goto-hack, and makes the code hard on the brain.
(obdisclaimer: for/else gets a mention in my OSCON python tutorial, so I'd appreciate it if you _don't_ rip it out in the next month <wink>)
Anthony
Tim Peters tim.peters@gmail.com writes:
I also suspect that if they weren't in the language already, a PEP to introduce them would fail, because
still_looking = True some loop: if found it: still_looking = False break if still_looking: # what would have been in the "else" clause
is clear and easy to write without it.
Oh, that's wierd. I didn't know there were "else" clauses for loops, but I would've expected the other semantics. That is, either the loop terminates normally, "else:" whatever.
At 02:48 PM 7/7/2005 -0400, Tim Peters wrote:
[Guido, on {for,while}/else] ...
The question remains whether Python would be easier to learn without them. And if so, the question would remain whether that's offset by their utility for experienced developers. All hard to assess impartially!
That's what I'm here for. I like loop "else" clauses, but have to admit that (a) I rarely use them; (b) most of the time I use them, my control flow is on the way to becoming so convoluted that I'm going to rewrite the whole function soon anyway;
Interesting; I usually intentionally write "else" clauses intending to *clarify* the code. That is, I often use it in cases where it's not strictly necessary, e.g.:
for thing in something: if blah: return thing else: return None
Because to me this clarifies that 'return None' is what happens if the loop "fails". Compare to:
for thing in something: if blah: return thing return None
This looks to me at first glance like code that always returns None after looping over 'something'.
Of course, these are trivial examples where reading the whole thing isn't a big deal; I'm more likely to use it when the loop or surrounding logic are a bit more complex, but I do also use it for fairly simple cases.
The interesting thing is that I think it *clarifies* the intent of the code, but I guess maybe that's only true for a small subset of Python programmers.
I suppose I wouldn't raise much of a fuss if the feature went away in 3.0, but I think I would miss it.
I also suspect that if they weren't in the language already, a PEP to introduce them would fail, because
still_looking = True some loop: if found it: still_looking = False break if still_looking: # what would have been in the "else" clause
is clear and easy to write without it.
*shudder* Okay, you just convinced me. "Else" should stay, because the above is much less readable and writable!
On Thu, Jul 07, 2005 at 03:03:35PM -0400, Phillip J. Eby wrote:
At 02:48 PM 7/7/2005 -0400, Tim Peters wrote:
[Guido, on {for,while}/else] ...
The question remains whether Python would be easier to learn without them. And if so, the question would remain whether that's offset by their utility for experienced developers. All hard to assess impartially!
That's what I'm here for. I like loop "else" clauses, but have to admit that (a) I rarely use them; (b) most of the time I use them, my control flow is on the way to becoming so convoluted that I'm going to rewrite the whole function soon anyway;
Interesting; I usually intentionally write "else" clauses intending to *clarify* the code. That is, I often use it in cases where it's not strictly necessary, e.g.:
for thing in something: if blah: return thing else: return None
Because to me this clarifies that 'return None' is what happens if the loop "fails".
I use else similarly, for defensive programming.
for (thing) in searchlist: if (matches(thing)): keeper = thing break else: raise ValueError("No thing matches()")
I can't say I use it for much else, if I really want a default I do found = None for (thing) in searchlist: if (matches(thing)): found = None break
That could end with 'else: found = None' to assign a default but I like the default to come first for readability.
-Jack
Jack Diederich jack@performancedrivers.com wrote:
I can't say I use it for much else, if I really want a default I do found = None for (thing) in searchlist: if (matches(thing)): found = None break
That could end with 'else: found = None' to assign a default but I like the default to come first for readability.
Actually I think assigning the fall-back value in an "else" branch is more readable. To some extent it's just a feeling, but there's two things: For one, it gives you all assignments to the result at closer, if not the same, indentation levels. More importantly, the value is unconditionally set by a single statement, namely the "for" construct, instead of by either the first or both, the second assignment basically making the first superfluous. Using "else" models better what you want to do, IMO.
Phillip J. Eby wrote:
At 02:48 PM 7/7/2005 -0400, Tim Peters wrote:
I also suspect that if they weren't in the language already, a PEP to introduce them would fail, because
still_looking = True some loop: if found it: still_looking = False break if still_looking: # what would have been in the "else" clause
is clear and easy to write without it.
*shudder* Okay, you just convinced me. "Else" should stay, because the above is much less readable and writable!
I think Aahz's point is a good one - conditional flow control can be most clearly represented using try blocks:
class BreakException(Exception): pass
try: some loop: if found it: raise BreakException except BreakException: pass else: # What would have been in the else clause
Defining 'else' on loops as short-hand for the above may make the intent of the clauses clearer (that is, for/else and while/else are more closely related to try statements than they are to if statements).
Regards, Nick.
[Guido van Rossum]
On 7/7/05, François Pinard pinard@iro.umontreal.ca wrote:
[Guido van Rossum]
I even wonder if else-clauses on for/while were a good idea.
I surely find them useful, and see them as a Python originality (a welcome one).
The question remains whether Python would be easier to learn without them.
Some of my co-workers, while being very dedicated and efficient to the production duties, are not especially fond on computer languages, and have only moderate pleasure learning them. They are very good people nevertheless! :-) After PL/I, C, some obscure languages you do not even know, and now Python, they receive it as just yet another in the series, and they accept taming themselves, slowly, around Python. I saw that the `else:' clause to `for' and `while' has been a surprise to them, and observe that they usually do not readily recognise cases where it would be useful. Yet, others in the gang are more enthusiastic, and they do not trip at all over various `else:'s. So, it much depends on the kind of relation between programmers and languages.
You know, Python would be easier to learn without all `__xyz__' methods, and without meta-classes :-). [Yet my feeling is that people overdo the difficulty of meta-classes, which do not deserve the prejudice they got.] The learning curve of `else:' is much smoother by comparison. `else:' _are_ useful in my experience, as I know I used stunts for years in other languages for achieving about the same effect. These are for elementary or basic day-to-day algorithms, and I cannot believe common problems are so different between a programmer and another.
All hard to assess impartially!
Granted. That's why I throw my opinion in this forum.
On 7/7/05, Guido van Rossum gvanrossum@gmail.com wrote:
The question remains whether Python would be easier to learn without them. And if so, the question would remain whether that's offset by their utility for experienced developers. All hard to assess impartially!
I think Python would clearly be easier to learn without them-- less syntax and semantics for loops that are in almost every program. I hardly ever use them myself, and I doubt that I'd really miss them. (Every time they come up, I need to think carefully about what they mean.)
As for impartial assessment, how many uses are there in the standard library? How many of those uses are clearer than other alternatives? Seems like an assessment of those questions is within reach.
Jeremy
PS Every time I switch between Python and C, I get confused about "elif" and "else if".
[Jeremy Hylton]
... PS Every time I switch between Python and C, I get confused about "elif" and "else if".
Mostly goes to show that you don't use Perl much ;-) Of course, in C99,
#define elif else if
is part of <stdlib.h>. Or maybe it isn't, and it just should have been? One of those -- or close enough.
I surely find them useful, and see them as a Python originality (a welcome one).
They are indeed an original invention. (One day I looked at the similarity between if and while and noticed that there was a use case for else after while too.)
The question remains whether Python would be easier to learn without them. And if so, the question would remain whether that's offset by their utility for experienced developers. All hard to assess impartially!
I dislike them because I can never read looping constructs with else: without thinking hard about what it does. Like:
for x in alist: if x == "foo": break else: print "foo was not found."
Is a better way of doing:
found = False for x in alist: if x == "foo": found = True break if not found: print "foo was not found."
So the else: is taken if the break wasn't executed. I think that is hard to grasp because it makes the for and break into a kind of conditional statement where break makes it evalute to true. But I think the best way to code this silly example is to write:
def finder(): for x in alist: if x == "foo": return True return False if not finder(): print "foo was not found."
Which is how I write when someone else might had used a "else." So IMHO, the use cases are weak. It's also confusing that try: has a different kind of else. "else" in "try" is a good thing - no exception occured. "else" in a for/while is (usually) a bad thing - as item was not found.
Guido van Rossum wrote:
I even wonder if else-clauses on for/while were a good idea. (The one on try is definitely a good idea since the use case is quite frequent and only clumsily handled otherwise; the use cases for else on for/while are less convincing IMO.)
I'm +1 on removing the else from the loops myself.
The else's acts somewhat different depending on weather it's on an if, try, for, or while loop. So it's four somewhat different behaviors for one keyword.
1. With an if, if you think in terms of flow testing you get the same results as if you look at it in in terms of value testing. Either the if-block will execute or the else-block will, but never any part of one and then the other. A binary solution to a binary problem.
2. With a try, It's a value test for no exception. Or you could consider it flow test for the try block completing.
3. In a while loop, it's a value test, where the else block gets executed if the while condition evaluates as false, the while block may or may not execute. You still need a flag to test for that.
4. In a for loop, it's a test of the iterator completing and generating a StopIteration exception. Which is somewhat implicit. The for block may or may not execute.
For Python 3000 it might be worth taking a look at flow control tests instead of value tests.
With loop flow control testing you have three possible values:
None: loop not started False: loop started but not completed, ie.. break True: loop completed naturally
* The current else behavior is an (if not False) test here.
I'm not sure how to test for the condition in a simple way. So it's still a -1 at this point. <shrug>
As for elif... it works for me. :)
Cheers, Ron
Ron Adam rrr@ronadam.com wrote:
- With an if, if you think in terms of flow testing you get the same
results as if you look at it in in terms of value testing. Either the if-block will execute or the else-block will, but never any part of one and then the other. A binary solution to a binary problem.
- With a try, It's a value test for no exception. Or you could
consider it flow test for the try block completing.
You might also look at it like this: There's a correspondence between the if and try statements with if/elif corresponding to except and else having the same meaning in both cases. With the exception of the try suite that sets the stage for exception handlers, both statements give you a set of branches (if/elif/else suites and execpt/else suites, resp.) exactly one of which will execute.
Which is one of the reasons why I came to think of my proposal starting this thread of being half-baked at best...
- In a while loop, it's a value test, where the else block gets
executed if the while condition evaluates as false, the while block may or may not execute. You still need a flag to test for that.
You're effectively arguing for do...while, right?
- In a for loop, it's a test of the iterator completing and
generating a StopIteration exception. Which is somewhat implicit. The for block may or may not execute.
This is something different IMO. You don't want to model condition testing, you want to act on a set of values which may or may not be empty. That's why I think you actually want the StopIteration stuff to be implicit.
Thomas Lotze wrote:
Ron Adam rrr@ronadam.com wrote:
- In a while loop, it's a value test, where the else block gets
executed if the while condition evaluates as false, the while block may or may not execute. You still need a flag to test for that.
You're effectively arguing for do...while, right?
Not arguing anything. Do-whiles are a flow control issue rather than a flow testing issue. A differnt problem.
Cheers, Ron
Ron Adam rrr@ronadam.com writes:
Guido van Rossum wrote:
I even wonder if else-clauses on for/while were a good idea. (The one on try is definitely a good idea since the use case is quite frequent and only clumsily handled otherwise; the use cases for else on for/while are less convincing IMO.)
I'm +1 on removing the else from the loops myself.
... in Python 3000, I hope you meant to qualify that with.
Cheers, mwh
Michael Hudson wrote:
Ron Adam rrr@ronadam.com writes:
Guido van Rossum wrote:
I even wonder if else-clauses on for/while were a good idea. (The one on try is definitely a good idea since the use case is quite frequent and only clumsily handled otherwise; the use cases for else on for/while are less convincing IMO.)
I'm +1 on removing the else from the loops myself.
... in Python 3000, I hope you meant to qualify that with.
Yes, that's what I meant.
Cheers, mwh
Guido van Rossum wrote:
I sometimes think it was a mistake to introduce elif just to save typing "else if".
The problem with the elwhile/elfor/eltry idea is that you're just as likely to need e.g. a "try" in the else clause of a while-loop as another while,
Here's an idea for Python 3000 which addresses both of these: Split 'elif' back up into 'else if', but also generalise it so that any 'else' can be followed by any suite-introducing statement. Then you get all possible combinations for free.
Greg
Greg Ewing wrote:
Guido van Rossum wrote:
I sometimes think it was a mistake to introduce elif just to save typing "else if".
The problem with the elwhile/elfor/eltry idea
is that you're just as likely to need e.g.
a "try" in the else clause of a while-loop as another while,
Here's an idea for Python 3000 which addresses both of these: Split 'elif' back up into 'else if', but also generalise it so that any 'else' can be followed by any suite-introducing statement. Then you get all possible combinations for free.
I don't think that's a good idea. What would the following monstrosity mean?:
if 0: print "Ran the if" else for item in (1, 2, 3): print item else try: print "No exception here!" except: pass else: print "Who's else is this, anyway?"
The use-case of 'elif' or 'else if' to avoid nested if statements is strong, but the use cases for the ability to mix compound statements together is significantly weaker.
Cheers, Nick.
Nick Coghlan wrote:
I don't think that's a good idea. What would the following monstrosity mean?:
if 0: print "Ran the if" else for item in (1, 2, 3): print item else try: print "No exception here!" except: pass else: print "Who's else is this, anyway?"
It is unambiguous. But:
The use-case of 'elif' or 'else if' to avoid nested if statements is strong, but the use cases for the ability to mix compound statements together is significantly weaker.
This is not even about use cases anymore, it's about usability. Indentation (by indicating nesting) serves well to recognize at first sight what belongs together, and what doesn't. Mixing compound statements breaks this, as it requires the reader to think about it twice, if that's even enough.