[Python-Dev] PEP 308: "then" "else" for deprecating "and" "or" side effects

Gary Herron gherron at islandtraining.com
Fri Feb 14 11:06:11 CET 2003

On Thursday 13 February 2003 07:17 pm, Christian Tismer wrote:
> Dear community,
> there has been some favor of my silly/simple a then b else c proposal.
> Please let me elaborate a little on this, with respect
> to the existing "and" and "or operators.

I read the following with interest, and started considering some
implications.  My conclusions follow at the end.

> "and" and "or" are two-headed beasts:
> At first glance, they pretend to be logical operators.
> At second inspection, they do this logic by promoting
> one of their operands.
> This is not obviously bad, and it is consistant with the logic.
> Due to the presence of a real boolean type, we
> should ask ourselves if "and" and "or" shouldn't be
> deprecated in their current meaning, towards being
> "boolean only"?
> I think it would be nicer if "and" and "or" would only
> produce true or false. But this would break lots of code.
> Therefore, I propose to keep them as they are, but to deprecate
> using them to carry their operand values instead of a true truth
> value.
> This would be still allowed, but there are new, more explicit
> operators, which should be used instead for new Python code:
> The binary operators "then" and "else".
> The ternary operator "then else".
> For a clear definition, see the function
> definitions below.
> Example: Parameter cleanup.
> Parameters are often massaged like this:
> "or" case:
>      arg = arg or "Default"
> The meaning of this phrase is:
> "If the user has provided no argument value that is
> true (non-empty or not 0 most of the time), then provide
> some default value".
>      arg = arg then arg else "Default"
> would be the verbose ternary replacement of this.
> A short replacement would read better:
>      arg = arg else "Default"
> which means "If arg is false, replace it by 'Default'".
> "and" case:
>      arg = arg and 42
> The meaning of this phrase is:
> "If the user provided any argument that is true, use some
> default value".
>      arg = arg then 42 else arg
> would be the verbose replacement of this.
> A short replacement would read better:
>      arg = arg then 42
> Summary:
> --------
> "and" and "or" are behaving like logical operators.
> They happen to do this by not providing a plain
> truth value, but by promoting one of their operands.
> "and" and "or" are valid operators, when used in a
> logical context, only, meaning only to use the truth
> value. They have the side effect of carrying an operand,
> which I regard as a design flaw, but this is bearable
> when used properly.
> Using "and" and "or", when they are meant as "then" or "else"
> should be deprectaed as bad style in the long term.
> Almost all instances of "and" and "or" used to carry a value
> can be replaced by "then" or "else" with ease, which makes the
> resulting code much more readable without prior knowledge.
> "and" and "or" do have a builtin perception of symmetry,
> which is not related to the truth, and hard to explain to
> newcomers.
> Therefore, I propose to deprecate their use to promote
> a value, and I propose to introduce "then" and "else"
> as dual operators, together with the "then else" pair
> as ternary operator, to be used in any context where
> the inquiry should promote the right operand without
> evaluating its truth value.
> Definition:
> -----------
> Here is my "cure" to "and" and "or" with side-effects:
>      a then b
>      --------
> is equivalent to
>      def then_proc(a, b):
>          if a:
>               return b
>          else:
>               return a
>      a else b
>      --------
> is equivalent to
>      def else_proc(a, b):
>          if a:
>               return a
>          else:
>               return b
>      a then b else c
>      ---------------
> is equivalent to
>      def then_else_proc(a, b, c):
>          if a:
>              return b
>          else:
>              return c
> "and" and "or" should be replaced by the above constructs,
> in all contexts where "and" and "or" are not pure logical,
> but are meant to propagate specific values, for all new code.
> kind regards -- chris
> p.s.: Please correct me positively, if I made a mistake at 4:15am

The above defines two binary operators "then" and "else" and a ternary
operator "then...else".  The question which occurred to me is: Since
the ternary operator is formed by what looks like two binary
operators, can the action of the ternary operator be defined in terms
of the actions of the two binary operators.  In other words, does the

  a then b else c         # the ternary operator

evaluate as either

  a then (b else c)       # two binary operators


  (a then b) else c       # two binary operators

The answer is *NO*, all three expressions evaluate to different
results.  More on that below.  

Now we are used to disambiguating expressions with multiple binary
operators by considering the precedence and (left or right)
associativity of the operators involved.  That is (a-b-c) evaluates as
(a-b)-c and (a+b*c) evaluates as a+(b*c).  However, in this
"then...else" expression, something which looks like (and could be
legitimately parsed as) two binary operations, in fact cannot be
disambiguated by either application of parentheses and must be treated
as a ternary operator.  

That in itself is bad enough, but to be a complete definition of these
operators, one must now define how, in a sequence of "then"s and
"else's, the parser can tease out which form ternary "then...else"
operators, and how those ternary "then...else" portions fit
(precedence wise and associativity wise) with the other ternary
"then...else"s and any remaining binary "then"s and "else"s.  These
rules, whatever thay may turn out to be, would probably be more
complex than I'd like to see in Python.

Here is a truth table for the three expressions.  The table not only
tells the truth value of the result, but shows, in parentheses,
*which* term is returned to express that truth value.  Note that the
three columns R, S, and T all differ for at least some set if input

 a   b   c      R      S      T
 F   F   F     F(c)   F(a)   F(c)
 F   F   T     T(c)   F(a)   T(c)
 F   T   F     F(c)   F(a)   F(c)
 F   T   T     T(c)   F(a)   T(c)
 T   F   F     F(b)   F(c)   F(c)
 T   F   T     F(b)   T(c)   T(c)
 T   T   F     T(b)   T(b)   T(b)
 T   T   T     T(b)   T(b)   T(b)


  R -> (a then b else c)
  S -> a then (b else c)
  T -> (a then b) else c

Dr. Gary Herron
gherron at islandtraining.com

More information about the Python-list mailing list