Thanks for reply,

I can see most of what you have written.

> But "encourages one-liners" is generally considered an anti-pattern in
> Python.  Let's see why,
Here I am a bit confused, how is this the case in the language containing list 
comprehensions?

I would understand if it was swapped with “bad quality & unreadable 1-liners”.

Also, I would rephrase “encourage 1-liners” to “promote readable and expressive 
structures that are balanced in their brevity versus complexity”.

I am not encouraging 1-liners, I am more arguing that certain things in 
relation to average complexity should take no more than 1-line. I am always 
very happy to write multiple lines.

E.g. I often use loops instead of list comprehensions:
l = list()
for i in range(10):
    l.append(func(i))
These 3 lines justify themselves. A reasonable amount of logic and complexity 
is contained in them. While I could not say the same about:
if a < 1:
    c = a
else:
    c = default
For what it does, it feels it should’t take more than half the space that the 
“for” loop above is taking.

Btw, here I would probably prefer:
def clamp_int(n: int, lo: int, hi: int):
    if lo > hi:
        raise ValueError(f'{lo=} > {hi=}')
    return lo <= n <= hi ? n : (n > hi ? hi : lo)
I emphasize readability more in high-level code, APIs, non-numeric routines and 
similar.

E.g. In numpy code I sacrifice a lot of that “english” readability for 
aesthetics and brevity, as it is closer to scientific space, where everything 
is pretty much named with 1-letter + glossary.

I think the place I am coming from is more about balance than brevity. In other 
words, outliers in multi-dimensional spacecan  feel awkward to me. Obviously, 
my dimensions might not be the same as someone else's.

> On 18 Jul 2023, at 16:38, Stephen J. Turnbull 
> <turnbull.stephen...@u.tsukuba.ac.jp> wrote:
> 
> 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/WH6YBYWXDUQK53IIP4CFOF6PQFSFMH35/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to