Beginners will often write code like this:
if val > 0: return +1 elif val < 0: return -1 elif val == 0: return 0
Now if you did this in Java, the compiler would produce an error saying that there is an execution path that does not return a value. Python does not give an error message, but it would be considered more idiomatic (and slightly more efficient) to have just "else:" in the third clause.
Here's an idea to address this. What do you think of the syntax
"else" expression ":"
for example:
if val > 0: return +1 elif val < 0: return -1 else val == 0: return 0
with the interpretation:
if val > 0: return +1 elif val < 0: return -1 else: assert val == 0 return 0
I have to say, I'm uncertain. I'm not sure this is even a good idea at all, and I'm not sure if it should translate into "assert expression" or whether it should be "if not expression: raise ValueError". What do you think?
-Peter Norvig
On Apr 13, 2013, at 11:24 AM, Peter Norvig wrote:
Here's an idea to address this. What do you think of the syntax "else" expression ":" for example: if val > 0: return +1 elif val < 0: return -1 else val == 0: return 0
I often write code like:
if cond1: doThing1() elif cond2: doThing2() # ... more steps here ... return something
I guess implicitly I think of this as a less verbose form of:
if cond1: doThing1() elif cond2: doThing2() else: pass # No need to do anything if not cond1 and not cond2
That is, the situation where every block of the condition ends in a return statement is a special case, and by no means universal to the use of if/elif/else. In particular, not every time I use if/elif do I want a "catch the remaining cases" block, since it is often only in some enumerated special circumstances I want any processing to occur in the compound block.
I think the "else with boolean" is definitely readable, modulo exactly what exception is raised if it is violated. However, it feels like the explicit 'assert' statement in those cases where we expect exhaustive conditions is already available. Moreover, we can always add a final else to document our belief that conditions are exhaustive:
if val > 0: return +1 elif val < 0: return -1 elif val == 0: return 0 else: raise ValueError("'val' is not negative, positive, or zero! Check the properties of arithmetic")
-- mertz@ THIS MESSAGE WAS BROUGHT TO YOU BY: v i gnosis Postmodern Enterprises s r .cx MAKERS OF CHAOS.... i u LOOK FOR IT IN A NEIGHBORHOOD NEAR YOU g s
That's a bad example because the comparisons would probably have raised a ValueError or TypeError for any, but I think being explicit is by far preferable, and just as concise, if not more so because you control the exception:
elif val < 0: return 0 elif value != 0: raise ValueError() return value
Of course you likely will have gotten a ValueError or TypeError already if you've done gt/lt comparisons on a value that turns out to also not be 0… If you're going to validate the data type eventually, why not do it at the top?
Shane Green www.umbrellacode.com 408-692-4666 | shane@umbrellacode.com
On Apr 13, 2013, at 12:01 PM, David Mertz mertz@gnosis.cx wrote:
On Apr 13, 2013, at 11:24 AM, Peter Norvig wrote:
Here's an idea to address this. What do you think of the syntax "else" expression ":" for example: if val > 0: return +1 elif val < 0: return -1 else val == 0: return 0
I often write code like:
if cond1: doThing1() elif cond2: doThing2() # ... more steps here ... return something
I guess implicitly I think of this as a less verbose form of:
if cond1: doThing1() elif cond2: doThing2() else: pass # No need to do anything if not cond1 and not cond2
That is, the situation where every block of the condition ends in a return statement is a special case, and by no means universal to the use of if/elif/else. In particular, not every time I use if/elif do I want a "catch the remaining cases" block, since it is often only in some enumerated special circumstances I want any processing to occur in the compound block.
I think the "else with boolean" is definitely readable, modulo exactly what exception is raised if it is violated. However, it feels like the explicit 'assert' statement in those cases where we expect exhaustive conditions is already available. Moreover, we can always add a final else to document our belief that conditions are exhaustive:
if val > 0: return +1 elif val < 0: return -1 elif val == 0: return 0 else: raise ValueError("'val' is not negative, positive, or zero! Check the properties of arithmetic")
-- mertz@ THIS MESSAGE WAS BROUGHT TO YOU BY: v i gnosis Postmodern Enterprises s r .cx MAKERS OF CHAOS.... i u LOOK FOR IT IN A NEIGHBORHOOD NEAR YOU g s
Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
On 4/13/2013 2:24 PM, Peter Norvig wrote:
Beginners will often write code like this:
if val > 0: return +1 elif val < 0: return -1 elif val == 0: return 0
So might a Python expert who knows that all three tests could return False for instances of some class. For instance, a fuzzy zero, or an interval that includes 0.
Or someone who like to be explicit about the appropriate guard for each return.
Now if you did this in Java, the compiler would produce an error saying that there is an execution path that does not return a value.
Not relevant since in Python all paths that end either raise or return.
Python does not give an error message,
because it is not an error.
but it would be considered more idiomatic (and slightly more efficient) to have just "else:" in the third clause.
Only when the last condition is the negation of the conjunction of the first two. Or when it is broader than that. I might actually write something like
else: # val = 0
to document the simplified negated conjunction, which in this case is the appropriate guard. Being explicit, at least with a comment, makes it easier for someone to re-order the branches, should there be reason to.
Python routinely allows correct but unidiomatic and inefficient code.
Here's an idea to address this.
I do not see that there is a problem to fix ;-).
What do you think of the syntax "else" expression ":"
A confusing solution to a non-problem ;-).
-- Terry Jan Reedy
On 13.04.13 22:21, Terry Jan Reedy wrote:
On 4/13/2013 2:24 PM, Peter Norvig wrote:
Beginners will often write code like this:
if val > 0: return +1 elif val < 0: return -1 elif val == 0: return 0
So might a Python expert who knows that all three tests could return False for instances of some class. For instance, a fuzzy zero, or an interval that includes 0.
Or float('nan').
An obligatory read for anyone who comes up with ideas like this: http://thedailywtf.com/Articles/ButAnything-Can-Happen!.aspx
no, this is different; it’s not for booleans, but for assertions, and could be used for e.g. exhaustive switches, e.g. it would make the first test in the following unnecessary:
if spam not in {"a", "b", "c"}: throw new ValueError("spam {} should be a, b, or c!".format(spam)) if spam == "a": foo() elif spam == "b": bar() else: baz()
i’m not saing i support the idea though. i’d rather see scala-like extensible pattern matching. that would solve this, the eternal switch debate, and more (using extractors).
is there a proposal for pattern matching? if not, i’ll come up with one ;)
2013/4/18 Yaroslav Fedevych yaroslav@fedevych.name
An obligatory read for anyone who comes up with ideas like this: http://thedailywtf.com/Articles/ButAnything-Can-Happen!.aspx
Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
On Fri, Apr 19, 2013 at 12:21 AM, Philipp A. flying-sheep@web.de wrote:
no, this is different; it’s not for booleans, but for assertions, and could be used for e.g. exhaustive switches, e.g. it would make the first test in the following unnecessary:
if spam not in {"a", "b", "c"}: throw new ValueError("spam {} should be a, b, or c!".format(spam)) if spam == "a": foo() elif spam == "b": bar() else: baz()
Or alternatively, you could write it as:
if spam == "genuine watch": foo() elif spam == "buy a college degree": bar() elif spam == "rich guy wants to move money offshore": baz() else: raise ValueError("Unrecognized spam '%s'!" % spam)
That removes the need to pre-check and match your if block.
ChrisA
On 18.04.13 17:33, Chris Angelico wrote:
On Fri, Apr 19, 2013 at 12:21 AM, Philipp A. flying-sheep@web.de wrote:
no, this is different; it’s not for booleans, but for assertions, and could be used for e.g. exhaustive switches, e.g. it would make the first test in the following unnecessary:
if spam not in {"a", "b", "c"}: throw new ValueError("spam {} should be a, b, or c!".format(spam)) if spam == "a": foo() elif spam == "b": bar() else: baz()
Or alternatively, you could write it as:
if spam == "genuine watch": foo() elif spam == "buy a college degree": bar() elif spam == "rich guy wants to move money offshore": baz() else: raise ValueError("Unrecognized spam '%s'!" % spam)
That removes the need to pre-check and match your if block.
Or alternative:
alternatives = { "genuine watch": foo, "buy a college degree": bar, "rich guy wants to move money offshore": baz, } try: alternative = alternatives[spam] except KeyError: raise ValueError("Unrecognized spam '%s'!" % spam) alternatives[spam]()
On 13/04/2013 19:24, Peter Norvig wrote:
Beginners will often write code like this:
if val > 0: return +1 elif val < 0: return -1 elif val == 0: return 0
Now if you did this in Java, the compiler would produce an error saying that there is an execution path that does not return a value. Python does not give an error message, but it would be considered more idiomatic (and slightly more efficient) to have just "else:" in the third clause.
Here's an idea to address this. What do you think of the syntax
"else" expression ":"
for example:
if val > 0: return +1 elif val < 0: return -1 else val == 0: return 0
with the interpretation:
if val > 0: return +1 elif val < 0: return -1 else: assert val == 0 return 0
I have to say, I'm uncertain. I'm not sure this is even a good idea at all, and I'm not sure if it should translate into "assert expression" or whether it should be "if not expression: raise ValueError". What do you think?
-Peter Norvig
Big -1 from me, if it ain't broke don't fix it.
Peter Norvig wrote:
Beginners will often write code like this:
if val > 0: return +1 elif val < 0: return -1 elif val == 0: return 0
Here's an idea to address this. What do you think of the syntax
"else" expression ":"
This will do nothing to help said beginner. He will continue to write "elif val == 0:", blissfully unaware that there could be another case that he hasn't thought of. If he had the presence of mind to realise that, he would have written something safer in the first place.
On 14/04/13 04:24, Peter Norvig wrote:
Beginners will often write code like this:
if val > 0: return +1 elif val < 0: return -1 elif val == 0: return 0
Now if you did this in Java, the compiler would produce an error saying that there is an execution path that does not return a value.
There's one difference between the languages right there: there is no such case for Python. If you pass something that doesn't match any of the three cases, say a NAN, the function will return None.
Python does not give an error message, but it would be considered more idiomatic (and slightly more efficient) to have just "else:" in the third clause.
Also incorrect, in a language which supports NANs, as Python does. (And Java, I believe, which may be why Java correctly tells you that there is a path with no return result.)
Here's an idea to address this. What do you think of the syntax
"else" expression ":"
I don't think it will help beginners, and for more experienced programmers, I don't think it is of much benefit over an explicit
else: assert expression, "message if the assert fails"
(or an explicit ValueError test, if more appropriate).
[...]
I have to say, I'm uncertain. I'm not sure this is even a good idea at all, and I'm not sure if it should translate into "assert expression" or whether it should be "if not expression: raise ValueError". What do you think?
I think that there's no one right answer. For some code, an assertion will be correct, and for others, an explicit test and ValueError (or some other exception!) will be correct. Neither is so obviously more common that Python should introduce syntax to favour one over the other.
Ah, yes, I should clarify that when I suggested:
elif val < 0: return -1 elif value != 0: raise ValueError()
I did NOT mean to propose it as the syntactical translation of anything; I was suggesting that beginning programmers should use that instead of the first approach. I would say that, between:
explicit is always better than implicit; in the face of ambiguity, refuse the temptation to buses; there should be one, and preferably only one, way to do it; and special cases aren't special enough to break rules.
Well, I like the way this one works now…
Shane Green www.umbrellacode.com 408-692-4666 | shane@umbrellacode.com
On Apr 13, 2013, at 7:36 PM, Steven D'Aprano steve@pearwood.info wrote:
On 14/04/13 04:24, Peter Norvig wrote:
Beginners will often write code like this:
if val > 0: return +1 elif val < 0: return -1 elif val == 0: return 0
Now if you did this in Java, the compiler would produce an error saying that there is an execution path that does not return a value.
There's one difference between the languages right there: there is no such case for Python. If you pass something that doesn't match any of the three cases, say a NAN, the function will return None.
Python does not give an error message, but it would be considered more idiomatic (and slightly more efficient) to have just "else:" in the third clause.
Also incorrect, in a language which supports NANs, as Python does. (And Java, I believe, which may be why Java correctly tells you that there is a path with no return result.)
Here's an idea to address this. What do you think of the syntax
"else" expression ":"
I don't think it will help beginners, and for more experienced programmers, I don't think it is of much benefit over an explicit
else: assert expression, "message if the assert fails"
(or an explicit ValueError test, if more appropriate).
[...]
I have to say, I'm uncertain. I'm not sure this is even a good idea at all, and I'm not sure if it should translate into "assert expression" or whether it should be "if not expression: raise ValueError". What do you think?
I think that there's no one right answer. For some code, an assertion will be correct, and for others, an explicit test and ValueError (or some other exception!) will be correct. Neither is so obviously more common that Python should introduce syntax to favour one over the other.
-- Steven _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
On Sun, Apr 14, 2013 at 4:24 AM, Peter Norvig peter@norvig.com wrote:
Beginners will often write code like this:
if val > 0: return +1 elif val < 0: return -1 elif val == 0: return 0
Now if you did this in Java, the compiler would produce an error saying that there is an execution path that does not return a value. Python does not give an error message, but it would be considered more idiomatic (and slightly more efficient) to have just "else:" in the third clause.
Here's an idea to address this. What do you think of the syntax
"else" expression ":"
for example:
if val > 0: return +1 elif val < 0: return -1 else val == 0: return 0
with the interpretation:
if val > 0: return +1 elif val < 0: return -1 else: assert val == 0 return 0
I have to say, I'm uncertain. I'm not sure this is even a good idea at all, and I'm not sure if it should translate into "assert expression" or whether it should be "if not expression: raise ValueError". What do you think?
I think the difference between:
if val > 0: return +1 elif val < 0: return -1 else val == 0: return 0
and:
if val > 0: return +1 elif val < 0: return -1 elif val == 0: return 0
is far too subtle to be helpful. If an if/elif chain is expected to be exhaustive and you want to ensure it remains that way during ongoing maintenance, you can already do:
if val > 0: return +1 elif val < 0: return -1 elif val == 0: return 0 else: raise RuntimeError("Unhandled input: {!r:100}".format(val))
(with the "else:" being optional if this is the last statement in a function)
In general, though, Python already decided on its answer to this question by always allowing a final "return None" to be implicit, even when there are explicit return statements elsewhere in the function.
Cheers, Nick.
-- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
I think that, if something special were added for this case, it may be best for it to be not overload the so incredibly well defined through the ages if/elif/ or else clauses, perhaps adding something new, like:
elifassert val==0: retur…
…you know, I've got say, I don't really recall finding myself in this situation very often in the first place. It seems like the most productive solution might be to plant an easter egg that suggests some of these alternative approaches!
Shane Green www.umbrellacode.com 408-692-4666 | shane@umbrellacode.com
On Apr 14, 2013, at 3:31 AM, Nick Coghlan ncoghlan@gmail.com wrote:
On Sun, Apr 14, 2013 at 4:24 AM, Peter Norvig peter@norvig.com wrote:
Beginners will often write code like this:
if val > 0: return +1 elif val < 0: return -1 elif val == 0: return 0
Now if you did this in Java, the compiler would produce an error saying that there is an execution path that does not return a value. Python does not give an error message, but it would be considered more idiomatic (and slightly more efficient) to have just "else:" in the third clause.
Here's an idea to address this. What do you think of the syntax
"else" expression ":"
for example:
if val > 0: return +1 elif val < 0: return -1 else val == 0: return 0
with the interpretation:
if val > 0: return +1 elif val < 0: return -1 else: assert val == 0 return 0
I have to say, I'm uncertain. I'm not sure this is even a good idea at all, and I'm not sure if it should translate into "assert expression" or whether it should be "if not expression: raise ValueError". What do you think?
I think the difference between:
if val > 0: return +1 elif val < 0: return -1 else val == 0: return 0
and:
if val > 0: return +1 elif val < 0: return -1 elif val == 0: return 0
is far too subtle to be helpful. If an if/elif chain is expected to be exhaustive and you want to ensure it remains that way during ongoing maintenance, you can already do:
if val > 0: return +1 elif val < 0: return -1 elif val == 0: return 0 else: raise RuntimeError("Unhandled input: {!r:100}".format(val))
(with the "else:" being optional if this is the last statement in a function)
In general, though, Python already decided on its answer to this question by always allowing a final "return None" to be implicit, even when there are explicit return statements elsewhere in the function.
Cheers, Nick.
-- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas