Amended the PEP to reflect some convergence on the newgroup:
* Listed the downsides of the current proposal. * Listed why '<cond> then <expr1> else <expr2>' is starting to be preferred over '<cond> and <expr1> or <expr2>'. * After BDFL comments, I withdrew my proposed c??a||b syntax and deleted the rejected c?a!b syntax. The remaining punctuation based contender is c?a:b. * After BDFL rejection of non-short-circuiting options, advocacy dropped sharply. Removed it from the list of contenders. The leading options on the table are: * (if <cond>: <expr1> else: <expr2>) * <cond> then <expr1> else <expr2> * <cond> ? <expr1> : <expr2> * no change
This commit is contained in:
parent
5ef89e80a2
commit
a975337001
117
pep-0308.txt
117
pep-0308.txt
|
@ -55,6 +55,12 @@ Proposal
|
|||
|
||||
This will be implemented if the proposal is accepted.
|
||||
|
||||
The downsides to the proposal are:
|
||||
|
||||
* the required parentheses
|
||||
* confusability with statement syntax
|
||||
* additional semantic loading of colons
|
||||
|
||||
Note that at most one of <expression1> and <expression2> is
|
||||
evaluated. This is called a "short-circuit expression"; it is
|
||||
similar to the way the second operand of 'and' / 'or' is only
|
||||
|
@ -72,17 +78,6 @@ Proposal
|
|||
|
||||
Alternatives
|
||||
|
||||
The original version of this PEP proposed the following syntax:
|
||||
|
||||
<expression1> if <condition> else <expression2>
|
||||
|
||||
The out-of-order arrangement was found to be too uncomfortable
|
||||
for many of participants in the discussion; especially when
|
||||
<expression1> is long, it's easy to miss the conditional while
|
||||
skimming.
|
||||
|
||||
---
|
||||
|
||||
Holger Krekel proposed a new, minimally invasive variant:
|
||||
|
||||
<condition> and <expression1> else <expression2>
|
||||
|
@ -92,12 +87,23 @@ Alternatives
|
|||
change that makes it complete. Many respondants on the
|
||||
newsgroup found this to be the most pleasing alternative.
|
||||
However, a couple of respondants were able to post examples
|
||||
that were mentally difficult to parse.
|
||||
that were mentally difficult to parse. Later it was pointed
|
||||
out that this construct works by having the "else" change the
|
||||
existing meaning of "and".
|
||||
|
||||
Christian Tismer proposed a variant of the same idea:
|
||||
As a result, there is increasing support for Christian Tismer's
|
||||
proposed variant of the same idea:
|
||||
|
||||
<condition> then <expression1> else <expression2>
|
||||
|
||||
The advantages are simple visual parsing, no required parenthesis,
|
||||
no change in the semantics of existing keywords, not as likely
|
||||
as the proposal to be confused with statement syntax, and does
|
||||
not further overload the colon. The disadvantage is the
|
||||
implementation costs of introducing a new keyword. However,
|
||||
unlike other new keywords, the word "then" seems unlikely to
|
||||
have been used as a name in existing programs.
|
||||
|
||||
---
|
||||
|
||||
Many C-derived languages use this syntax:
|
||||
|
@ -112,32 +118,19 @@ Alternatives
|
|||
|
||||
---
|
||||
|
||||
David Ascher proposed a variant that doesn't have this problem:
|
||||
The original version of this PEP proposed the following syntax:
|
||||
|
||||
<condition> ? <expression1> ! <expression2>
|
||||
<expression1> if <condition> else <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.
|
||||
The out-of-order arrangement was found to be too uncomfortable
|
||||
for many of participants in the discussion; especially when
|
||||
<expression1> is long, it's easy to miss the conditional while
|
||||
skimming.
|
||||
|
||||
---
|
||||
|
||||
Raymond Hettinger proposed a variant that removes the
|
||||
arbitrariness:
|
||||
|
||||
<condition> ?? <expression1> || <expression2>
|
||||
|
||||
The ?? and || are not arbitrary as they strongly suggest testing
|
||||
and alternation. Another merit is that that existing operators
|
||||
are not overloaded. Having two characters at each step also helps
|
||||
visually separate the subordinate expressions. Alas, the BDFL
|
||||
prefers the proposed syntax and considers this alternative "too
|
||||
Perlish".
|
||||
|
||||
---
|
||||
|
||||
Many people suggest adding a new builtin instead of extending the
|
||||
syntax of the language, e.g.:
|
||||
Some have suggested adding a new builtin instead of extending the
|
||||
syntax of the language. For example:
|
||||
|
||||
cond(<condition>, <expression1>, <expression2>)
|
||||
|
||||
|
@ -153,23 +146,19 @@ Alternatives
|
|||
|
||||
Summary of the Current State of the Discussion
|
||||
|
||||
Groups are falling into one of five camps:
|
||||
Groups are falling into one of three camps:
|
||||
|
||||
1. Adopt a ternary operator built using punctuation characters.
|
||||
It would look something like:
|
||||
<condition> ?? <expression1> || <expression2>
|
||||
1. Adopt a ternary operator built using punctuation characters:
|
||||
|
||||
2. Adopt a ternary operator built using existing keywords.
|
||||
The proposal listed above is the leading example.
|
||||
<condition> ? <expression1> : <expression2>
|
||||
|
||||
3. Adopt a ternary operator built using a new keyword.
|
||||
The leading contender looks like this:
|
||||
cond(<condition>, <expression1>, <expression2>)
|
||||
2. Adopt a ternary operator built using new or existing keywords.
|
||||
The leading examples are:
|
||||
|
||||
4. Adopt a function without short-circuit behavior:
|
||||
cond(<condition>, <expression1>, <expression2>)
|
||||
<condition> then <expression1> else <expression2>
|
||||
(if <condition>: <expression1> else: <expression2>)
|
||||
|
||||
5. Do nothing.
|
||||
3. Do nothing.
|
||||
|
||||
The first two positions are relatively similar.
|
||||
|
||||
|
@ -184,29 +173,12 @@ Summary of the Current State of the Discussion
|
|||
operators. The other downside is that it creates some degree of
|
||||
confusion between the two meanings and two usages of the keywords.
|
||||
|
||||
The third form introduces a new keyword and arranges the arguments
|
||||
separated by commas. Adding a new keyword is to be generally
|
||||
avoided. But the form is clear, short, and direct. There is a
|
||||
possible confusion with function syntax which implies that all the
|
||||
arguments are evaluated rather than short-circuited. This idea
|
||||
was presented by the BDFL and should be considered a contender for
|
||||
the final vote. The exact keyword is still an open question. One
|
||||
proposal was iif(), but it looks like a typo and can be confused
|
||||
with if-and-only-if which has a different, well-defined
|
||||
mathematical meaning.
|
||||
|
||||
The fourth position is much more conservative. Adding a new
|
||||
function, cond(), is trivially easy to implement and fits easily
|
||||
within the existing python model. Users of older versions of
|
||||
Python will find it trivial to simulate. The downside is that it
|
||||
does not provide the sought-after short-circuit evaluation (see
|
||||
the discussion below on the need for this). The bigger downside
|
||||
is that the BDFL opposes *any* solution that does not provide
|
||||
short circuit behavior.
|
||||
Those difficulties are overcome by options which introduce new
|
||||
keywords which take more effort to implement.
|
||||
|
||||
The last position is doing nothing. Arguments in favor include
|
||||
keeping the language simple and concise; maintaining backwards
|
||||
compatibility; and that any every use cases can already be already
|
||||
compatibility; and that any every use case can already be already
|
||||
expressed in terms of "if" and "else". Lambda expressions are an
|
||||
exception as they require the conditional to be factored out into
|
||||
a separate function definition.
|
||||
|
@ -214,12 +186,7 @@ Summary of the Current State of the Discussion
|
|||
The arguments against doing nothing are that the other choices
|
||||
allow greater economy of expression and that current practices
|
||||
show a propensity for erroneous uses of "and", "or", or one their
|
||||
more complex, visually unappealing workarounds.
|
||||
|
||||
It should also be mentioned that most supporters of any of the
|
||||
first four positions do not want an imperfect solution and would
|
||||
sooner have no change than create a wart to attain their desired
|
||||
functionality.
|
||||
more complex, less visually unappealing workarounds.
|
||||
|
||||
|
||||
Short-Circuit Behavior
|
||||
|
@ -236,15 +203,15 @@ Short-Circuit Behavior
|
|||
expression.
|
||||
|
||||
# Example where all three reasons apply
|
||||
data = isinstance(source, file) ?? source.readlines()
|
||||
|| source.split()
|
||||
data = isinstance(source, file) ? source.readlines()
|
||||
: source.split()
|
||||
|
||||
1. readlines() moves the file pointer
|
||||
2. for long sources, both alternatives take time
|
||||
3. split() is only valid for strings and readlines() is only
|
||||
valid for file objects.
|
||||
|
||||
Supporters of the cond() function point-out that the need for
|
||||
Supporters of a cond() function point-out that the need for
|
||||
short-circuit evaluation is rare. Scanning through existing code
|
||||
directories, they found that if/else did not occur often; and of
|
||||
those only a few contained expressions that could be helped by
|
||||
|
|
Loading…
Reference in New Issue