FAQ
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

Search Discussions

  • Terry Hancock at Sep 7, 2005 at 2:11 pm

    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
  • Kay Schluehr at Sep 7, 2005 at 5:17 pm

    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
  • Terry Reedy at Sep 7, 2005 at 6:20 pm
    "Kay Schluehr" <kay.schluehr at gmx.net> wrote in message
    news:1126113430.910646.69290 at g44g2000cwa.googlegroups.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
  • Kay Schluehr at Sep 7, 2005 at 7:57 pm

    Terry Reedy wrote:
    "Kay Schluehr" <kay.schluehr at gmx.net> wrote in message
    news:1126113430.910646.69290 at g44g2000cwa.googlegroups.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
  • Steven Bethard at Sep 7, 2005 at 11:02 pm

    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
  • Antoon Pardon at Sep 8, 2005 at 12:15 pm
    Op 2005-09-07, Terry Reedy schreef <tjreedy at udel.edu>:
    "Kay Schluehr" <kay.schluehr at gmx.net> wrote in message
    news:1126113430.910646.69290 at g44g2000cwa.googlegroups.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
  • Duncan Booth at Sep 8, 2005 at 12:42 pm

    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.
  • Antoon Pardon at Sep 8, 2005 at 2:34 pm

    Op 2005-09-08, Duncan Booth schreef <duncan.booth at 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
  • Terry Hancock at Sep 7, 2005 at 10:53 pm

    On Wednesday 07 September 2005 02:44 pm, Paul Rubin wrote:
    Terry Hancock <hancock at 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
  • Bengt Richter at Sep 8, 2005 at 8:37 am

    On Wed, 7 Sep 2005 17:53:46 -0500, Terry Hancock wrote:
    On Wednesday 07 September 2005 02:44 pm, Paul Rubin wrote:
    Terry Hancock <hancock at 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
  • Terry Hancock at Sep 9, 2005 at 3:28 pm

    On Thursday 08 September 2005 04:30 am, Paul Rubin wrote:
    Terry Hancock <hancock at 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
  • Antoon Pardon at Sep 12, 2005 at 7:55 am

    Op 2005-09-09, Terry Hancock schreef <hancock at anansispaceworks.com>:
    On Thursday 08 September 2005 04:30 am, Paul Rubin wrote:
    Terry Hancock <hancock at 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

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedSep 7, '05 at 10:29a
activeSep 12, '05 at 7:55a
posts13
users7
websitepython.org

People

Translate

site design / logo © 2022 Grokbase