PEP 308: Pep Update

Norman Petry npetry1 at canada.com
Thu Feb 27 01:06:21 EST 2003


On Thu, 27 Feb 2003 14:51:03 +1300, Greg Ewing (using news.cis.dfn.de)
wrote:

> Tim Rowe wrote:
>> has anybody already pointed out that
>> practically every C/C++ coding standard (certainly /all/ I've ever
>> seen) deprecates the use of the ?: ternary operator, because it's
>> infamous for producing unmaintainable code?
> 
> But is that because of the idea of a conditional expression in general,
> or just the particular syntax used in C?

Probably the latter.

I think that the C syntax for the ternary is very poor, mostly because
there is nothing intuitively obvious about it.

C? trueValue : falseValue

is a bad syntax in general, but _particularly_ for Python because (imho):

1) it uses symbols, rather than keywords, which are meaningless unless the
reader is already familiar with the construct from another programming
language (since they have no obvious analogue in mathematics or some
natural language).  This makes it an especially poor choice for Python,
which has important applications as a teaching (i.e. first) language.

2) it is arbitrary, in that nothing about the syntax would suggest that
the trueValue should precede the colon (i.e. C? falseValue : trueValue is
equally logical, since a more natural order might be False(0) : True(1)).
The problem is that the symbols used to form the ternary are not
suggestive enough to convey a clear meaning (admittedly the question mark
is barely OK). Arbitrary language features are harder to remember, and
make the language more difficult to use casually.

3) it is confusing, since using the colon to separate alternatives would
conflict with the established meaning of that symbol in Python.  In
Python, the ':' is generally used to signal the beginning of a conditional
block (similar to keywords like 'then' and 'do' in other languages), or
represent some type of range.  A comma or semicolon would be a more
'pythonic' symbol to use as a separator for a sequence of (2) values.

4) it is somewhat illogical to have the condition appear at the beginning
of the expression, since it is one of the two _values_ that gets assigned
to the result.  Python arithmetic expressions normally use infix
operators, with the type of the result often being the same/similar to the
value that begins the expression.  While there are of course many
exceptions to this, a better syntax would be one which at least suggests
the result type to the reader just by looking at the beginning of the
ternary expression.  For similar reasons, it would be equally bad to begin
the ternary expression with a keyword (result = if...?!)

While the C language does have some good points, it's not exactly a model
of clear and elegant syntax.  One of the reasons I prefer to program in
Python is because it uses a largely keyword-based syntax rather than
thoughtlessly apeing the mistakes made in the design of C/C++/PHP... (too
bad about the screwy assignment (=) and equality (==) symbols, but I guess
even Python can't be perfect ;-) I think that adopting C-like syntax for
the ternary would be a very bad idea.

After reading the hundreds of postings on this topic, I still feel that
the syntax shown in the original version of the PEP (x if C else y) is the
only one with any real merit.  It offers many advantages:

1) keyword based, with an obvious and unambiguous meaning even to someone
unfamiliar with the ternary construct.

2) common result appears at the beginning of the expression, making it
easy to determine the likely result type and value.

3) reuses existing keywords (if, else) unlike similar proposals like 'x
when C else y' which convey precisely the same meaning in a verbose and
non-backwards-compatible way.  Adding an entirely new reserved word solely
for the benefit (?) of a rarely-used construct seems like an especially
bad idea.

4) uses the 'if' keyword in a novel ordering that avoids confusion with
the use of 'if' in the context of a conditional statement (this is a
FEATURE, not a BUG ;-).  The current proposal, for example ((if C: x else:
y)) requires surrounding parentheses partly to avoid this problem.

5) avoids lots of extraneous symbols (parens, colons, etc.) that are
needed in other formats to achieve clarity.

6) provides a simple, elegant, and obvious way of achieving an n-way
selection without requiring additional keywords, parens, etc. (x if C1
else y if C2 else z ...)

The objections to the 'x if C else y' syntax have all been very weak,
imho.  Most people who have criticised the proposal have done little more
than to point out that the condition appears in the middle of the
expression (unlike C, which presumably does things the "right" way).  Of
course, this is no argument at all -- it's merely restating what the
proposed syntax *is*, without explaining why there's a problem with doing
it that way.  I think the REAL problem is that these critics are familiar
with how the ternary is represented in C and similar languages, so having
the test in the middle looks unnatural at first sight.  Some people have
claimed that "you can't read it either LtR or RtL", but I really can't
understand this argument at all (how do YOU read "lunch = pizza if hungry
else salad", if not left-to-right?)  I'd bet that 'x if C else y' will
look perfectly natural to experienced programmers within a month if it
gets adopted, and would look natural RIGHT NOW to those who have never
used the ternary in other languages (we'll then all be wondering why C has
such a brain-damaged ternary syntax :-)

To me, 'x if C else y' looks perfectly natural (I don't often code in C),
and has the elegance that I expect in the design of Python.

My vote on PEP 308 (if anyone cares) is:

  +1 : x if C else y
   0 : NO TERNARY
-0.5 : (if C: x else: y)
  -1 : ALL OTHER PROPOSALS

Please reinstate "x if C else y" as the recommended syntax for PEP-308.


--
Norman Petry




More information about the Python-list mailing list