|| ||Guido van Rossum <firstname.lastname@example.org>|
|| ||For review: PEP 308 - If-then-else expression|
|| ||Fri, 07 Feb 2003 12:14:40 -0500|
Given that if-then-else expressions keep being requested, I hereby put
forward a proposal. I am neutral on acceptance of the proposal; I'd
like the c.l.py community to accept or reject it or come up with a
counter-proposal. Please understand that I don't have a lot of time
to moderate the discussion; I'll just wait for the community to
discuss the proposal and agree on some way to count votes, then count
Title: If-then-else expression
Version: $Revision: 1.1 $
Last-Modified: $Date: 2003/02/07 17:03:31 $
Author: Guido van Rossum
Type: Standards Track
Requests for an if-then-else ("ternary") expression keep coming up
on comp.lang.python. This PEP contains a concrete proposal of a
fairly Pythonic syntax. This is the community's one chance: if
this PEP is approved with a clear majority, it will be implemented
in Python 2.4. If not, the PEP will be augmented with a summary
of the reasons for rejection and the subject better not come up
again. While I am the author of this PEP, I am neither in favor
nor against this proposal; it is up to the community to decide.
If the community can't decide, I'll reject the PEP.
The proposed syntax is as follows:
<expression1> if <condition> else <expression2>
This is evaluated like this:
- First, <condition> is evaluated.
- If <condition> is true, <expression1> is evaluated and is the
result of the whole thing.
- If <condition> is false, <expression2> is evaluated and is the
result of the whole thing.
Note that at most one of <expression1> and <expression2> is
evaluated. This is called a "shortcut expression"; it is similar
to the way the second operand of 'and' / 'or' is only evaluated if
the first operand is true / false.
To disambiguate this in the context of other operators, the
"if...else" part in the middle acts like a left-associative binary
operator with a priority lower than that of "or", and higher than
that of "lambda".
Examples of how this works out:
x if C else y if D else z <==> x if C else (y if D else z)
x or y if C else z <==> (x or y) if C else z
x if C else y or z <==> x if C else (y or z)
lambda: x if C else y <==> lambda: (x if C else y)
x if C else lambda: y <==> SyntaxError
x if C else y, z <==> (x if C else y), z
x, y if C else z <==> x, (y if C else z)
Many C-derived languages use this syntax:
<condition> ? <expression1> : <expression2>
I reject this for several reasons: the colon already has many uses
in Python (even though it would actually not be ambiguous, because
the question mark requires a matching colon); for people not used
to C-derived language, it is hard to understand.
Eric Raymond proposed a variant that doesn't have this problem:
<condition> ? <expression1> ! <expression2>
While cute, this suffers from the Perlish problem of using
arbitrary punctuation with an arbitrary meaning; and it's no
easier to understand than the ?: form.
If we could live with adding a new keyword, we could use:
if <condition> then <expression1> else <expression2>
Apart from the problem of introducing a new keyword for a minor
feature, this also suffers from ambiguity at the start of a
statement; for example:
if verbose then sys.stdout.write("hello\n") else None
could be an syntactically correct expression statement, but starts
with 'if', which makes the parser believe it is the start of an
'if' statement. To resolve this, the syntax would have to require
parentheses, which makes it uglier. However, this form has the
advantage of evaluating strictly from left to right (not that that
is a requirement for being Pythonic -- list comprehensions don't).
This document has been placed in the public domain.
--Guido van Rossum (home page: http://www.python.org/~guido/)
to post comments)