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
> <[email protected]> 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 -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/WH6YBYWXDUQK53IIP4CFOF6PQFSFMH35/
Code of Conduct: http://python.org/psf/codeofconduct/