By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,818 Members | 1,223 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,818 IT Pros & Developers. It's quick & easy.

PEP-able? Expressional conditions

P: n/a
One of the main reasons Pythons anonymous function lambda is considered
to be "broken" is Pythons disability to put statements into expressions
and support full functionality. Many attempts to improve lambdas syntax
had also been attempts to break the expression/statement distinction in
one or the other way. None of this suggestions have ever been
successfull in solving severe problems caused by Pythons indentation
syntax and I guess they will never succeed. On the other hand I do not
see immediately the necessaty to support the full range of Python
constructs in small anonymous functions that are dedicated to fit into
one line.

Instead of pushing statements into expressions one can try to do it the
other way round and model expressions with the functionality of
statements. The most important use-cases are assignments and
conditions. I want to consider conditions only.

In Python conditional statements have the form:

if COND_1:
BLOCK_1
elif COND_2:
BLOCK_2
....
else:
BLOCK_n

Before turning this kind of statement into an expression we have to
restrict the BLOCKs to expressions:

if COND_1:
EXPR_1
elif COND_2:
EXPR_2
....
else:
EXPR_n

Since the conditional statement is traversed sequentially we can
transform it into a sequence of (COND,EXPR) pairs. Finally we have to
recover the conditional semantics.

I want to propose a new associative binary operator that acts on
(COND,EXPR) pairs like a projection on the second EXPR argument of a
pair in case of COND evaluated True.

This function works much like

def cond(pair1, pair2):
COND1,EXPR1 = pair1
if COND1:
return EXPR1
try:
COND2,EXPR2 = pair2
if COND2:
return EXPR2
except TypeError:
return pair2
Alternative syntax proposals:

(a) (COND1,EXPR1) || (COND2,EXPR2)
(b) (COND1,EXPR1) case (COND2,EXPR2)
(c) (COND1,EXPR1) owise (COND2,EXPR2)
(d) (COND1,EXPR1) ? (COND2,EXPR2)

Regards,
Kay

Sep 7 '05 #1
Share this Question
Share on Google+
14 Replies


P: n/a
On Wednesday 07 September 2005 05:29 am, Kay Schluehr wrote:
Instead of pushing statements into expressions one can try to do it the
other way round and model expressions with the functionality of
statements. Alternative syntax proposals:

(a) (COND1,EXPR1) || (COND2,EXPR2)
(b) (COND1,EXPR1) case (COND2,EXPR2)
(c) (COND1,EXPR1) owise (COND2,EXPR2)
(d) (COND1,EXPR1) ? (COND2,EXPR2)


You appear to be reinventing the C "ternary operator". This is
definitely a dead horse. There was already a PEP, and it was
refused.

If you actually want this, you're going to have to implement it
with a function:

def ternary(condition, true_result, false_result):
if condition:
return true_result
else:
return false_result

Almost as good, and you don't have to talk curmudgeons into providing
it for you.

Cheers,
Terry

--
Terry Hancock ( hancock at anansispaceworks.com )
Anansi Spaceworks http://www.anansispaceworks.com

Sep 7 '05 #2

P: n/a
Terry Hancock wrote:
On Wednesday 07 September 2005 05:29 am, Kay Schluehr wrote:
Instead of pushing statements into expressions one can try to do it the
other way round and model expressions with the functionality of
statements.
Alternative syntax proposals:

(a) (COND1,EXPR1) || (COND2,EXPR2)
(b) (COND1,EXPR1) case (COND2,EXPR2)
(c) (COND1,EXPR1) owise (COND2,EXPR2)
(d) (COND1,EXPR1) ? (COND2,EXPR2)


You appear to be reinventing the C "ternary operator". This is
definitely a dead horse. There was already a PEP, and it was
refused.


Well, I'm not inspired by C and the operator is not ternary but binary
and associative. Nevertheless the behaviour of the ternary condition
operator exists as a limit case. The expression becomes more a kind of
a horizontal squeezed switch. Therefore the "case" keyword proposal.

It might become more obvious if one chains the expression using more
terms:

(a') (COND1,EXPR1) || (COND2,EXPR2) || ... || (CONDk,EXPRk)
(b') (COND1,EXPR1) case (COND2,EXPR2) case ... case (CONDk,EXPRk)
If you actually want this, you're going to have to implement it
with a function:

def ternary(condition, true_result, false_result):
if condition:
return true_result
else:
return false_result


No, as I explained it is not a ternary operator and it can't easily be
implemented using a Python function efficiently because Python does not
support lazy evaluation. One usually does not want to evaluate all
conditions as well as all the results ( when passing them into the
function ) but evaluate conditional expressions sequentially and stop
at the first true condition. Well I would indeed like to go even
further and introduce lazy tuples this way but I wanted to notice the
responses to an obvious use case first.

Kay

Sep 7 '05 #3

P: n/a

"Kay Schluehr" <ka**********@gmx.net> wrote in message
news:11*********************@g44g2000cwa.googlegro ups.com...
No, as I explained it is not a ternary operator and it can't easily be
implemented using a Python function efficiently because Python does not
support lazy evaluation.
By *carefully* using the flow-control operators 'and' and 'or', you can
often get what you want *now*, no PEP required.
One usually does not want to evaluate all
conditions as well as all the results ( when passing them into the
function ) but evaluate conditional expressions sequentially and stop
at the first true condition.


*If* bool(result_expression_i) == True for all i, (except maybe last
default expression), which is true for some actual use cases, then the
following expression evaluates to the result corresponding to the first
'true' condition (if there is one) or to the default:

c0 and r0 or c1 and r1 or c2 and r2... or default.

I have only seen real examples with one and-pair, like (x < 0) and -x or x
for absolute value.

Terry J. Reedy

Sep 7 '05 #4

P: n/a
Terry Hancock <ha*****@anansispaceworks.com> writes:
def ternary(condition, true_result, false_result):
if condition:
return true_result
else:
return false_result

Almost as good, and you don't have to talk curmudgeons into providing
it for you.


Not the same at all. It evaluates both the true and false results,
which may have side effects.
Sep 7 '05 #5

P: n/a
Terry Reedy wrote:
"Kay Schluehr" <ka**********@gmx.net> wrote in message
news:11*********************@g44g2000cwa.googlegro ups.com...
No, as I explained it is not a ternary operator and it can't easily be
implemented using a Python function efficiently because Python does not
support lazy evaluation.


By *carefully* using the flow-control operators 'and' and 'or', you can
often get what you want *now*, no PEP required.
One usually does not want to evaluate all
conditions as well as all the results ( when passing them into the
function ) but evaluate conditional expressions sequentially and stop
at the first true condition.


*If* bool(result_expression_i) == True for all i, (except maybe last
default expression), which is true for some actual use cases, then the
following expression evaluates to the result corresponding to the first
'true' condition (if there is one) or to the default:

c0 and r0 or c1 and r1 or c2 and r2... or default.

I have only seen real examples with one and-pair, like (x < 0) and -x or x
for absolute value.

Terry J. Reedy


O.K. you win. One can complete this particular evaluation scheme by
introducing a little wrapper:

def Id(val):
return lambda:val

(c0 and Id(r0) or c1 and Id(r1) or c2 and Id(r2)... or Id(default))()

This works for each sequence r0,r1,... without any restictions.

Kay

Sep 7 '05 #6

P: n/a
On Wednesday 07 September 2005 02:44 pm, Paul Rubin wrote:
Terry Hancock <ha*****@anansispaceworks.com> writes:
def ternary(condition, true_result, false_result):
if condition:
return true_result
else:
return false_result

Almost as good, and you don't have to talk curmudgeons into providing
it for you.


Not the same at all. It evaluates both the true and false results,
which may have side effects.


If you are depending on that kind of nit-picking behavior,
you have a serious design flaw, a bug waiting to bite you,
and code which shouldn't have been embedded in an expression
in the first place.
--
Terry Hancock ( hancock at anansispaceworks.com )
Anansi Spaceworks http://www.anansispaceworks.com

Sep 7 '05 #7

P: n/a
Kay Schluehr wrote:
Terry Reedy wrote:
*If* bool(result_expression_i) == True for all i, (except maybe last
default expression), which is true for some actual use cases, then the
following expression evaluates to the result corresponding to the first
'true' condition (if there is one) or to the default:

c0 and r0 or c1 and r1 or c2 and r2... or default.


O.K. you win. One can complete this particular evaluation scheme by
introducing a little wrapper:

def Id(val):
return lambda:val

(c0 and Id(r0) or c1 and Id(r1) or c2 and Id(r2)... or Id(default))()

This works for each sequence r0,r1,... without any restictions.


Or use a list as the "wrapper":

(c0 and [r0] or c1 and [r1] or c2 and [r2] ... or [default])[0]

Not that I'd actually encourage anyone to write this code. ;-)

STeVe
Sep 7 '05 #8

P: n/a
On Wed, 7 Sep 2005 17:53:46 -0500, Terry Hancock <ha*****@anansispaceworks.com> wrote:
On Wednesday 07 September 2005 02:44 pm, Paul Rubin wrote:
Terry Hancock <ha*****@anansispaceworks.com> writes:
> def ternary(condition, true_result, false_result):
> if condition:
> return true_result
> else:
> return false_result
>
> Almost as good, and you don't have to talk curmudgeons into providing
> it for you.


Not the same at all. It evaluates both the true and false results,
which may have side effects.


If you are depending on that kind of nit-picking behavior,
you have a serious design flaw, a bug waiting to bite you,
and code which shouldn't have been embedded in an expression
in the first place.

Or you might know excatly what you are doing ;-)

Regards,
Bengt Richter
Sep 8 '05 #9

P: n/a
Terry Hancock <ha*****@anansispaceworks.com> writes:
Not the same at all. It evaluates both the true and false results,
which may have side effects.


If you are depending on that kind of nit-picking behavior,
you have a serious design flaw, a bug waiting to bite you,
and code which shouldn't have been embedded in an expression
in the first place.


Are you kidding? Example (imagine a C-like ?: operator in Python):

x = (i < len(a)) ? a[i] : None # make sure i is in range

Where's the design flaw? Where's the bug waiting to bite? That's a
completely normal use of a conditional expression. If the conditional
expression works correctly, this does the right thing, as intended.
If both results get evaluated, it throws a subscript out of range
error, not good.

Every time this topic comes up, the suggestions that get put forth are
far more confusing than just adding conditional expressions and being
done with it.
Sep 8 '05 #10

P: n/a
Op 2005-09-07, Terry Reedy schreef <tj*****@udel.edu>:

"Kay Schluehr" <ka**********@gmx.net> wrote in message
news:11*********************@g44g2000cwa.googlegro ups.com...
No, as I explained it is not a ternary operator and it can't easily be
implemented using a Python function efficiently because Python does not
support lazy evaluation.


By *carefully* using the flow-control operators 'and' and 'or', you can
often get what you want *now*, no PEP required.


Which is why I don't understand the resistance against introducing
such a beast.

Whether it is a ternary operator or something more general, the
proposed construction are usually more readable than the
python construction with the same functionality.
The decorator syntax IMO provided much less improvement in
readability for functionality that was already provided
and that got implemented.
A ternary operator (or suitable generalisation) would IMO
provide a greater improvement what readability is concerned
but is resisted all the way.

--
Antoon Pardon
Sep 8 '05 #11

P: n/a
Antoon Pardon wrote:
Which is why I don't understand the resistance against introducing
such a beast.
The idea has already been discussed to death. Read PEP 308 to see what was
proposed, discussed, and why the PEP was eventually rejected:

http://www.python.org/peps/pep-0308.html: Status: Rejected
...
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 the BDFL is co-author of this PEP, he is neither in
favor nor against this proposal; it is up to the community to
decide. If the community can't decide, the BDFL will reject the
PEP.
...
Following the discussion, a vote was held. While there was an
overall
interest in having some form of if-then-else expressions, no one
format was able to draw majority support. Accordingly, the PEP was
rejected due to the lack of an overwhelming majority for change.
Also, a Python design principle has been to prefer the status quo
whenever there are doubts about which path to take.


Sep 8 '05 #12

P: n/a
Op 2005-09-08, Duncan Booth schreef <du**********@invalid.invalid>:
Antoon Pardon wrote:
Which is why I don't understand the resistance against introducing
such a beast.
The idea has already been discussed to death. Read PEP 308 to see what was
proposed, discussed, and why the PEP was eventually rejected:


So what? If the same procedure would have been followed concerning
the decorator syntax, it would have been rejected too for the same
reasons.
http://www.python.org/peps/pep-0308.html:
Status: Rejected
...
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 the BDFL is co-author of this PEP, he is neither in
favor nor against this proposal; it is up to the community to
decide. If the community can't decide, the BDFL will reject the
PEP.
...
Following the discussion, a vote was held. While there was an
overall
interest in having some form of if-then-else expressions, no one
format was able to draw majority support. Accordingly, the PEP was
rejected due to the lack of an overwhelming majority for change.
Also, a Python design principle has been to prefer the status quo
whenever there are doubts about which path to take.


IMO this is worded in a misleading way. It wasn't that there was lack
of an overwhelming majority for change. 436 supported at least one
of the options and only 82 rejected all options. So it seems 436 voters
out of 518 supported the introduction of a ternary operator.

Yes no format was able to draw majority support but that is hardly
suprising since there where 17 formats to choose from. I find
the fact that people were unable to choose one clear winner out
of 17 formats in one vote, being worded as: "lack of an overwhelming
majority for change" at the least not very accurate and probably
misleading or dishonest.

--
Antoon Pardon

Sep 8 '05 #13

P: n/a
On Thursday 08 September 2005 04:30 am, Paul Rubin wrote:
Terry Hancock <ha*****@anansispaceworks.com> writes:
Not the same at all. It evaluates both the true and false results,
which may have side effects.
If you are depending on that kind of nit-picking behavior,
you have a serious design flaw, a bug waiting to bite you,
and code which shouldn't have been embedded in an expression
in the first place.


Are you kidding? Example (imagine a C-like ?: operator in Python):

x = (i < len(a)) ? a[i] : None # make sure i is in range

Where's the design flaw?


It's a syntax error. See?
x = (i < len(a)) ? a[i] : None # make sure i is in range

File "<stdin>", line 1
x = (i < len(a)) ? a[i] : None # make sure i is in range
^
SyntaxError: invalid syntax

That's a pretty serious design flaw.

You see, I'm not discussing an imaginary Python interpreter here.
Where's the bug waiting to bite? That's a
completely normal use of a conditional expression. If the conditional
expression works correctly, this does the right thing, as intended.
If both results get evaluated, it throws a subscript out of range
error, not good.
No. It throws a syntax error, as I demonstrated.
Every time this topic comes up, the suggestions that get put forth are
far more confusing than just adding conditional expressions and being
done with it.


If it's so easy, then do it, and quit whining. You could easily
have published an alternative "better" ternary function instead
of just complaining that mine "isn't right", by which you mean
only that it doesn't work exactly as it would in C, or in your
imaginary Python interpreter.

Myself, I just can't see how writing:

if (i < len(a)): x = a[i]
else: x = None

is gonna kill you. It's also not by any means a solution so obvious
that I would not want to see the special case on it's own line.

After all, in most cases where I would use a limiter like this, I'd
want the special case to be handled by something other than None. Or
I'd want to raise an exception, even. Which, come to think of it,
I wouldn't even have to code, would I? The thing is, if you return
None like this, you won't be able to treat it the same as the normal
output, so you're still going to have to check the result. Which just
means you've moved the complexity upwards (almost always a bad move
which replicates effort -- another design flaw).

If you want to go and argue with Guido over this, go ahead. I'm all
for a ternary operator.

But IIRC, that parrot is dead. It's an ex-parrot.

Hence, I'm not big on discussing what sort of fake wings we can
glue onto it. It isn't that hard to live without a ternary operator.

You're just trying to program a C idiom in Python and cussing the
fact that it doesn't translate. Sorry, loads of stuff doesn't, but
it doesn't necessarily make that a design flaw.

But if you really must avoid evaluating the results in your hand-crafted
ternary function, that is of course, also possible. Go ahead and
write it and share it here, please.

--
Terry Hancock ( hancock at anansispaceworks.com )
Anansi Spaceworks http://www.anansispaceworks.com

Sep 9 '05 #14

P: n/a
Op 2005-09-09, Terry Hancock schreef <ha*****@anansispaceworks.com>:
On Thursday 08 September 2005 04:30 am, Paul Rubin wrote:
Terry Hancock <ha*****@anansispaceworks.com> writes:
> > Not the same at all. It evaluates both the true and false results,
> > which may have side effects.
>
> If you are depending on that kind of nit-picking behavior,
> you have a serious design flaw, a bug waiting to bite you,
> and code which shouldn't have been embedded in an expression
> in the first place.
Are you kidding? Example (imagine a C-like ?: operator in Python):

x = (i < len(a)) ? a[i] : None # make sure i is in range

Where's the design flaw?


It's a syntax error. See?
x = (i < len(a)) ? a[i] : None # make sure i is in range File "<stdin>", line 1
x = (i < len(a)) ? a[i] : None # make sure i is in range
^
SyntaxError: invalid syntax

That's a pretty serious design flaw.

You see, I'm not discussing an imaginary Python interpreter here.


Nobody is, but the general consensus about a ternary operator
has always been that it should have lazy evaluataion.
That is even mentioned in the PEP.
http://www.python.org/peps/pep-0308.html

The BDFL's position is that short-circuit behavior is essential
for an if-then-else construct to be added to the language.

And you did claim that depending on side effects was a serious design
flaw. And as far as I understand what you wrote that was independant
of the language used.

Where's the bug waiting to bite? That's a
completely normal use of a conditional expression. If the conditional
expression works correctly, this does the right thing, as intended.
If both results get evaluated, it throws a subscript out of range
error, not good.


No. It throws a syntax error, as I demonstrated.


Which is a dishonest remark. The way you made the remark, made it
a claim about algorithmic design, independant of the language
chosen or the specific construct chosen to interpret it.

That Paul chose a construct that is not syntactic python to dispute
your claim, is beside the point.
Every time this topic comes up, the suggestions that get put forth are
far more confusing than just adding conditional expressions and being
done with it.


If it's so easy, then do it, and quit whining. You could easily
have published an alternative "better" ternary function instead
of just complaining that mine "isn't right", by which you mean
only that it doesn't work exactly as it would in C, or in your
imaginary Python interpreter.


There have been alternatives enough that have been published.
It is not a matter of publishing yet an other alternative.
It is just that the BDFL has declare this a no no.
Myself, I just can't see how writing:

if (i < len(a)): x = a[i]
else: x = None

is gonna kill you. It's also not by any means a solution so obvious
that I would not want to see the special case on it's own line.
And how do I do this in a list comprehension?

Myself I couldn't see how writing:

def fun(...):
...

fun = deco(fun)

Would kill anyone, but decorator syntax appeared anyway.
After all, in most cases where I would use a limiter like this, I'd
want the special case to be handled by something other than None. Or
I'd want to raise an exception, even. Which, come to think of it,
I wouldn't even have to code, would I? The thing is, if you return
None like this, you won't be able to treat it the same as the normal
output, so you're still going to have to check the result. Which just
means you've moved the complexity upwards (almost always a bad move
which replicates effort -- another design flaw).
Examples given here, are done so to make a point. The example itself
may never been used in actual code, but code that is similar enough
in behaviour, may. Try to look at the argument one is trying to make
instead of looking at insignificant details.
If you want to go and argue with Guido over this, go ahead. I'm all
for a ternary operator.

But IIRC, that parrot is dead. It's an ex-parrot.


Yes probably, but the fact that it is a dead parrot, doesn't make
the idea bad. I sometimes get the impression that just because
Guido declared a subject dead, some people feel obligated to
argue how bad it would have been anyway.

--
Antoon Pardon
Sep 12 '05 #15

This discussion thread is closed

Replies have been disabled for this discussion.