Dom Grigonis writes:

 > I came to this, because people seem to want one-liners for certain
 > things and what I came up with is that maybe more concise if-else
 > expression could help.

But "encourages one-liners" is generally considered an anti-pattern in
Python.  Let's see why,

 > # Fairly reasonable case.

 > def foo(a: bool, c: float, d: float)
 >     val = a ? (c ? c : d) : (d ? d : c)
 >     return val

What's not so great here?

1.  The argument names are not going to be single characters, unless
    you intentionally name that way for the sake of one-line-ism.
    That severely detracts from your claim of readability.  The
    one-liner is arguably[1] more readable than the Python version,
    but you've definitely made the whole function less readable.

2.  Comparing floats, even against zero, is a bad idea.  So I would
    wrap them in math.isclose:

    val = a ? (not isclose(c, 0) ? c : d) : (not isclose(d, 0) ? d : c)

    Pretty long, not that easy to read.  Of course if you had
    intelligible variable names it would be worse.

    The point is *not* to give you a hard time about comparing floats
    for equality, we've all done that.  It's that in even in this
    example, done safely you have more complex expressions than just
    variable references.  In general you will have function calls
    adding parentheses -- and thus confusion.  Perhaps there will be
    lists or tuples involved.  You can precompute them and assign
    them to short name variables, but then you lose the one-liner-ness.

3.  OK, how about ints then?  Yes, that would work, but how frequently
    are you going to be comparing against 0?  Here's a more realistic
    case, with readable short argument names:

    def clamp_int(n: int, lo: int, hi: int):
        # I wouldn't elide this test because if lo > hi you get a
        # plausible but necessarily erroneous value
        if lo > hi:
            raise ValueError(f'lo = {lo} > {hi} = hi')
        val = n < lo ? lo : (n > hi ? hi : n)
        return val

    Agreed, the expression using Python's syntax would be worse, but I
    think this is much more readable:

    def clamp_int(n: int, lo: int, hi: int):
        if lo > hi:
            raise ValueError(f'lo = {lo} > {hi} = hi')
        if n < lo:
            val = lo
        elif n > hi:
            val = hi
        else:
            val = n
        return val

    and it would be more readable yet if you got rid of the
    assignments and just returned the value as soon as you see it:

    def clamp_int(n: int, lo: int, hi: int):
        if lo > hi:
            raise ValueError(f'lo = {lo} > {hi} = hi')
        # Hi, David!  Default first!!
        if lo <= n <= hi:        # Yes, Virginia, valid Python!
            return n
        elif n > hi:
            return hi
        else:
            return lo

    (Yes, I know that some folks argue that suites should have one
    entry point and one exit point, but I don't think it's a problem
    here because of the extreme symmetry and simplicity of the
    conditional.  IMHO YMMV of course)

 > I dare you to do a 1-liner with current if-else.

I do use ternary expressions occasionally, but almost never nested.
Writing one-liners is never a goal for me, in part because my old eyes
can't take in more than 35-40 characters in a gulp.

 > So maybe, just maybe, making already existing expression more
 > readable can also be a valid suggestion?

We *won't do that*, because of backward compatibility.  The syntax of
an exist expression cannot change without invalidating a lot of
existing code.  That's one reason why the bar to new syntax is so
high, and it took so long to get the ternary expression: you really
want to get it right.  That's why Python (like C!) prefers to add to
the stdlib rather than the language.

Now, you can add a new one that does the same thing, and that's been
done.  IIRC it took a while to get +=, and C-like ++/-- increment
operators have been requested over and over again.  AFAIK the async
syntaxes do nothing that can't be done with generators, but they make
it a lot easier to do it right in the most common cases.

 > As I said, in my opinion it would solve many existing queries and
 > requests, just because certain things would become very pleasant
 > and obvious how to do in simple one-liners.

One-liners are almost by definition less readable.  Even in math
papers we break equations into a series of definitions and then build
up the final equation from there.  As M. Spivak put it in *Calculus on
Manifolds*,

    Stokes' theorem shares three important attributes with many fully
    evolved major theorems:
    1.  It is trivial.
    2.  It is trivial because the terms appearing in it have been
        properly defined.
    3.  It has significant consequences.

When I have the time and knowledge, I aspire to programming that
way. :-)  YMMV

 > Simpler and more logically convenient if-else combined with other
 > elegant python expressions would potentially fill that gap.

I guess.  It's certainly true that Python pre-walrus operator had no
good solution to the "loop and a half" problem.  But I've been
programming long enough it's hard to get myself to use the walrus
operator in the "assign and return" fashion that C's assignment
operator so frequently is.

 > From where I currently stand it just seems fairly happy middle
 > solution between: very concise narrow functionality requests and
 > very verbose ways of how they need to be done at the moment.

But the functionality you request is extremely narrow in a different
sense.  At least the way people who develop Python (and GNU Mailman,
where I program Python in anger, as they say) taught me, very
frequently the most concise expression is not the most readable, and
"readability counts".  So as above I would likely exand these
expressions into statement syntax in many cases anyway, despite having
a more concise syntax.

 > I fully appreciate how likely what I am proposing is going to be
 > even considered. But I really think it should be.

I think you will find almost noone in Python development who would
agree that it *should* be.  Even if you 100% discount the "20 years
late" objection that stops it before it gest started.

A lot of the arguments you make would be good arguments, or would have
the form of good arguments, for other features.  Your "sense" of
language development is good, IMO.  But if you want to contribute to
Python development you need to choose the features to support more in
line with conventional wisdom.  For example, Chris A's PEP on default
argument processing (is that the PEP 671 mentioned earlier?) would
resolve what many consider to be a wart, and it hasn't been rejected,
just postponed.  Or you could choose one that is not merely
duplicating existing functionality with syntax ore to your taste.

Steve

_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/ZGBGAH5U4K34CQLJEC5CHRUGKYHM2FBM/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to