[Python-checkins] python/nondist/peps pep-0308.txt,1.9,1.10

rhettinger@users.sourceforge.net rhettinger@users.sourceforge.net
Mon, 10 Feb 2003 21:43:59 -0800


Update of /cvsroot/python/python/nondist/peps
In directory sc8-pr-cvs1:/tmp/cvs-serv19656

Modified Files:
	pep-0308.txt 
Log Message:
Updated the PEP for GvR.

* Out of order evaluation is out of favor.
* So are ideas that do not provide for short-circuiting.
* (if <condition>: <expression1> else: <condition2>) is in vogue.
* <condition> ?? <expression1> || <expression2> is a new contender.
* cond(<condition>, <expression1>, <condition2>) is viable if implemented
      as a keyword and has short-circuit behavior.
* Added a summary of a few ideas from the last couple hundred posts
      from comp.lang.python.



Index: pep-0308.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0308.txt,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -d -r1.9 -r1.10
*** pep-0308.txt	9 Feb 2003 05:12:54 -0000	1.9
--- pep-0308.txt	11 Feb 2003 05:43:56 -0000	1.10
***************
*** 3,7 ****
  Version: $Revision$
  Last-Modified: $Date$
! Author: Guido van Rossum
  Status: Draft
  Type: Standards Track
--- 3,7 ----
  Version: $Revision$
  Last-Modified: $Date$
! Author: Guido van Rossum and Raymond D. Hettinger
  Status: Draft
  Type: Standards Track
***************
*** 28,32 ****
      The proposed syntax is as follows:
  
!         <expression1> if <condition> else <expression2>
  
      This is evaluated like this:
--- 28,33 ----
      The proposed syntax is as follows:
  
! 	(if <condition>: <expression1> else: <expression2>) 
! 
  
      This is evaluated like this:
***************
*** 41,63 ****
  
      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 right-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)
- 
      Note: a common way to emulate an if-then-else expression is:
  
--- 42,49 ----
  
      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 evaluated if
      the first operand is true / false.
  
      Note: a common way to emulate an if-then-else expression is:
  
***************
*** 72,82 ****
  Alternatives
  
      Many C-derived languages use this syntax:
  
          <condition> ? <expression1> : <expression2>
  
!     Eric Raymond even implemented this.  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.
--- 58,77 ----
  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.
+ 
+     ---
+ 
      Many C-derived languages use this syntax:
  
          <condition> ? <expression1> : <expression2>
  
!     Eric Raymond even implemented this.  The BDFL rejected 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.
***************
*** 94,168 ****
      ---
  
!     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).
  
!     ---
  
!     To deal with the problem of adding a new keyword, this variant has
!     been proposed:
  
-         if <condition> : <expression1> else <expression2>
  
!     This has the same ambiguity problem as the previous one (I would
!     even say more so), and lacks symmetry.  It also begs the question
!     why there isn't a colon after the 'else'.  But this:
  
!         if <condition> : <expression1> else: <expression2>
  
!     is even more confusing because it resembles the if statement so
!     much.  (A solution that *doesn't* resemble the if statement is
!     better IMO since it should be obvious at first glance whether
!     we're dealing with an if expression or with an if statement.
!     Placing the 'if' in the middle somehow satisfies this
!     requirement.)
  
!     ---
  
!     Many people suggest adding a new builtin instead of extending the
!     syntax of the language, e.g.:
  
!         ifelse(condition, expression1, expression2)
  
!     This won't work the way a syntax extension will because both
!     expression1 and expression2 must be evaluated before the function
!     is called.  There's no way to short-circuit the expression
!     evaluation.
  
  
! Variations
  
!     It has been proposed to make the 'else' part optional.  This would
!     be a really bad idea.  I showed:
  
!         x = e if C
  
!     to several people.  They all thought that if C was false, it would
!     leave x unchanged.  So don't even think about this one!
  
!     ---
  
!     Another variant proposes to use 'when' instead of 'if':
  
!         <expression1> when <condition> else <expression2>
  
!     I don't see the advantage of 'when' over 'if'; it adds a new
!     keyword which is a major extra hurdle to introduce this.  I think
!     that using a different keyword suggests that the semantics are
!     different than those of an 'if' statement; but they really aren't
!     (only the syntax is different).
  
  
--- 89,232 ----
      ---
  
!     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 as
!     alternative number one.
  
!     ---
  
!     Many people suggest adding a new builtin instead of extending the
!     syntax of the language, e.g.:
  
!         ifelse(<condition>, <expression1>, <expression2>)
  
!     This won't work the way a syntax extension will because both
!     expression1 and expression2 must be evaluated before the function
!     is called.  There's no way to short-circuit the expression
!     evaluation.
  
  
! Summary of the Current State of the Discussion
  
!     Groups are falling into one of five camps:
  
!     1.  Adopt a ternary operator built using punctuation characters.
! 	It would look something like:
! 	    <condition> ?? <expression1>  || <expression2>
  
!     2.  Adopt a ternary operator built using existing keywords.
! 	The proposal listed above is the leading example.
  
!     3.  Adopt a ternary operator built using a new keyword.
!         The leading contender looks like this:
! 	    cond(<condition>, <expression1>, <expression2>)							 
  
!     4.  Adopt a function without short-circuit behavior:
!             cond(<condition>, <expression1>, <expression2>) 
  
!     5.  Do nothing.
  
+     The first two positions are relatively similar.
  
!     Some find that any form of punctuation makes the language more
!     cryptic.  Others find that punctuation style is appropriate
!     for expressions rather than statements and helps avoid a COBOL
!     style:  3 plus 4 times 5.
  
!     Adapting existing keywords attempts to improve on punctuation
!     through explicit meaning and a more tidy appearance.  The downside
!     is some loss of the economy-of-expression provided by punctuation
!     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.
  
!     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
!     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.
  
!     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.
  
! 
! Short-Circuit Behavior
! 
!     The principal difference between the ternary operator
!     and the cond() function is that the latter provides an expression
!     form but does not provide short-circuit evaluation.
! 
!     Short-circuit evaluation is desirable on three occasions:
!                                                          
!     1. When an expression has side-effects
!     2. When one or both of the expressions are resource intensive
!     3. When the condition serves as a guard for the validity of the
!       expression.
! 
!     #  Example where all three reasons apply
!     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
!     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 cond() or a ternary operator; and that most of those
!     had no need for short-circuit evaluation.  Hence, cond() would
!     suffice for most needs and would spare efforts to alter the
!     syntax of the language.
! 
!     More supporting evidence comes from scans of C code
!     bases which show that its ternary operator used very rarely
!     (as a percentage of lines of code).
! 
!     A counter point to that analysis is that the availability
!     of a ternary operator helped the programmer in every case
!     because it spared the need to search for side-effects.
!     Further, it would preclude errors arising from distant
!     modifications which introduce side-effects.  The latter case
!     has become more of a reality with the advent of properties
!     where even attribute access can be given side-effects.
! 
!     Still, the point is moot since the BDFL opposes solutions
!     which do not provide short-circuit behavior.