On Tue, 18 Jul 2023 at 23:41, Stephen J. Turnbull
<turnbull.stephen...@u.tsukuba.ac.jp> wrote:
> 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)

That's overly simplistic; there are a lot of times when it's
absolutely fine to compare floats for equality, particularly with
zero, where the idea of "close" can be ill-defined. But this is the
difficulty with toy examples - we have no idea how realistic this
actually is. For now, though, I'd be inclined to keep the semantics
unchanged and just look at the syntax.

>     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.

This is true, almost trivially so; one-liners aren't all that common
because real-world use-cases are often complicated. However, they DO
exist. It'd be nice to have really good examples but we may well not
have that luxury.

> 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)

def clamp_int(n: int, lo: int, hi: int):
    if lo > hi:
        raise ValueError(f'{lo = } > {hi = }')
    return max(lo, min(n, hi))

Nobody said we weren't allowed to use builtins, right? :)

> Now, you can add a new one that does the same thing, and that's been
> done.  IIRC it took a while to get +=

Note that augmented operators are not simply shorthands for the
expanded version. There are a few differences between:

a.b.c.d.e += value

and

a.b.c.d.e = a.b.c.d.e + value

including that the basis object (a.b.c.d) would only be evaluated
once, and especially, the addition is done in-place if supported (eg
with lists).

> 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.

A plain async function pretty much IS a generator, but without the
risk of removing the last await point and having the function stop
being a generator. But async generators are also a thing, and there's
no easy way to make a generator-generator with two different types of
yield in it.

But yes, in general, these aren't drastically new pieces of
functionality - they're nice improvements to readability and
expressiveness. I can write an application that uses generators
instead of async functions (and my current flagship non-Python project
does exactly that), as long as I'm not using generators for anything
else. I can write something with no augmented assignment operators, as
long as I always use list extend instead of addition, and don't mind
the reevaluation of intermediate components (which, most of the time,
is only a performance matter, not a correctness one). But it's
definitely nice to have them.

ChrisA
_______________________________________________
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/4A2NOURRWABHNPKOHHBE5UTZPLRXPUGD/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to