[Python-ideas] Re: Conditional 1-line expression in python (Dom Grigonis)

2023-07-18 Thread Chris Angelico
On Wed, 19 Jul 2023 at 11:51, Dom Grigonis  wrote:
>
> Coming back to deferred evaluation,
>
> https://peps.python.org/pep-0671/
> These 2 aren’t really orthogonal in functionality. Maybe in implementation.
> But PEP671 is a certain subset of deferred evaluation as it can achieve the 
> same with 1 extra line at the start of the function’s body.

No, it's not a subset of deferred evaluation, as has been stated
clearly in the PEP and discussed many times in the past.

Deferred evaluation is HARD. It's easy to handwave everything and
pretend that it magically gets evaluated at the exact right time, but
how do you actually define that? What are the scoping rules? Does it
create a closure?

Try creating an actual concrete specification and you may find out why
it hasn't been implemented yet.

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/UYBQ4VHCDWUQSQ5B7DUU4NPNUKFIORPR/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Conditional 1-line expression in python (Dom Grigonis)

2023-07-18 Thread Dom Grigonis
Coming back to deferred evaluation,

https://peps.python.org/pep-0671/ 
These 2 aren’t really orthogonal in functionality. Maybe in implementation.
But PEP671 is a certain subset of deferred evaluation as it can achieve the 
same with 1 extra line at the start of the function’s body.

--
Most importantly:
If deferred evaluation had a CONCISE keyword/operator, it would actually solve 
my (and several other) requests/proposals.
def ifelse(cond, if_true, if_false):
return if_true if cond else if_false

IF = ifelse


def __init__(self, a=None, b=None):
self.a = ifelse(a is not None, a, ?Foo())
self.b = IF(b is not None, b, `Bar()`)
hopefully it would not be `later`...

This way users could define their own constructs via callables & control order, 
evaluation and brevity to their liking.

--
https://peps.python.org/pep-0463/  could 
also be achieved with a function.
def trye(expr, err, default):
try:
return expr
except err:
return default

value = trye(`dct[key]`, KeyError, 'No Value')

--
https://peps.python.org/pep-0505/ 
def naw(a, b):
if a is not None:
return a
else:
return b

a = None
naw(a, `expr()`)

# OR Infix operator:
a |naw| `expr()`
It starts to seem that it would solve all of the things I was looking at to a 
satisfactory degree (given a concise keyword obviously...).

--
With certain additions, could even break & continue...
from statements import Break, Continue

def ifelsebc(cond, val, else_break=True):
if cond:
return val
elif else_break:
return `Break(0)`
else:
return `Continue(0)`

a = 0
while True:
a += ifelsebc(a < 5, 1, else_break=True)

print(a)# 5
The issue with lambda is that it has to be handled differently, or code has to 
check for its possibility, while deferred evaluation integrates seamlessly into 
already existing code.

IMO, it would be an excellent addition. And all this would come as a side 
effect, rather than main intent (which is dask.delay functionality if I 
understood correctly).

How likely you think is it going to happen? Given PEP number it doesn’t sound 
very promising...

> On 18 Jul 2023, at 09:45, Chris Angelico  wrote:
> 
> On Tue, 18 Jul 2023 at 16:25, Dom Grigonis  wrote:
>> 
>> Yes, thank you, this would definitely be nice to have.
>> 
>> Although, "A generic system for deferred evaluation has been proposed at 
>> times“ sound better if it was a superset of PEP505. Could you refer me to 
>> any resources about such considered system?
>> 
> 
> Hrm, you'd probably have to scour the archives. It's one of those
> things that comes up periodically and spawns a discussion thread, but
> never really gets to a concrete proposal. The best I can find is this,
> which never even got submitted to the official PEP repository, but
> it's someone's attempt to make something that could potentially become
> one, so it's a start.
> 
> https://github.com/DavidMertz/peps/blob/master/pep-.rst
> 
> The trouble is, it's really REALLY hard to pin down useful semantics
> for deferred evaluation. We already have lambda functions, which cover
> a lot of situations, leaving a lot of uncertainty as to what's being
> handled by this new proposal - and since no proposal ever truly comes
> from a single person, that results in a certain amount of chaos.
> 
> 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/YRGQV3U2GJFHYN2LXLW7PCP7MH22LFWI/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal for get_or function in Python dictionaries

2023-07-18 Thread Dom Grigonis
Ok, fair I am confusing definitions.

Expressiveness, defined by modern dictionary: “the quality of effectively 
conveying a thought or feeling”.

Let me correct myself.

Although I see that expressiveness is important, I think variable:

Functionality / verbosity - can be as important.

> On 18 Jul 2023, at 23:59, Chris Angelico  wrote:
> 
> On Wed, 19 Jul 2023 at 06:41, Dom Grigonis  wrote:
>> 
>> When you put it from this perspective, it seems to make sense, however, I do 
>> not agree.
>> 
>> To me, from first principles it seems it’s all about condensing more 
>> complexity in smaller modular packages.
>> 
>> That is why I am a bit confused, when someone argues that it is not about 
>> conciseness, but about expressiveness.
> 
> You're confused, yet you refuse to accept that you might be wrong. I
> don't think there's any point me continuing to discuss this with you.
> 
> 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/M76SNAINFPIVM6NLVZAAKCTJTM2NRCVG/
> Code of Conduct: http://python.org/psf/codeofconduct/

___
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/H53ZTUOCS7VS4OAFGOMXURL46EB22BWV/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal for get_or function in Python dictionaries

2023-07-18 Thread Chris Angelico
On Wed, 19 Jul 2023 at 06:41, Dom Grigonis  wrote:
>
> When you put it from this perspective, it seems to make sense, however, I do 
> not agree.
>
> To me, from first principles it seems it’s all about condensing more 
> complexity in smaller modular packages.
>
> That is why I am a bit confused, when someone argues that it is not about 
> conciseness, but about expressiveness.

You're confused, yet you refuse to accept that you might be wrong. I
don't think there's any point me continuing to discuss this with you.

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/M76SNAINFPIVM6NLVZAAKCTJTM2NRCVG/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal for get_or function in Python dictionaries

2023-07-18 Thread Dom Grigonis
When you put it from this perspective, it seems to make sense, however, I do 
not agree.

To me, from first principles it seems it’s all about condensing more complexity 
in smaller modular packages.

Leaving modularity aside, condensing more complexity in smaller packages in 
programming area is most often expressed via abstractions. Starting from binary 
we build more expressive components and applications, where each layer uses 
less and less code to do more and more complex things.

Yes, when you increase complexity without increasing the size - you say 
expressiveness.
But when you make package smaller without increasing complexity - you say 
conciseness.

So "expressiveness ~ 1/conciseness" if both aspects of phenomena are taken into 
account.

And decreasing number of characters is not conciseness, but rather 1 dimension 
of it, nevertheless important.

That is why I am a bit confused, when someone argues that it is not about 
conciseness, but about expressiveness.

I see the POV, that say ok x-size, y-expressiveness, however I think in this 
case, it is not expressiveness, but rather functionality.

So x-size(however one defines it), y-functionality.
Expressiveness = y/x
Conciseness = x/y
Thus, expressiveness = 1 / conciseness.

Maybe I am not using the terminology correctly (seems right to me, given 
etymology of these words), but this is just to explain what I meant.


> On 18 Jul 2023, at 18:34, Paul Moore  wrote:
> 
> On Tue, 18 Jul 2023 at 16:13, Dom Grigonis  > wrote:
> To me, they are in the inverse relationship.
> 
> Terseness ~ 1 / expressiveness.
> 
> No, they are unrelated (in general).
> 
> Terseness is nothing more than "can I use fewer characters?" and is almost 
> always the wrong thing to do in isolation (yes, if things get *yoo* verbose 
> they can be hard to comprehend, but that's about going to extremes, not about 
> terseness as such).
> 
> Expressiveness is about matching the *concepts* involved to the problem. So 
> list comprehensions are expressive because they declaratively say what the 
> content of the list should be, and avoid the unnecessary concepts around how 
> you build the list. It's irrelevant how many characters are involved, what 
> matters is that you can omit saying "first create an empty list, now add 
> elements like  one by one..."
> 
> Paul

___
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/6YRQLO74MSD3F3IJEWXIOJ7BOOHNELSE/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal for get_or function in Python dictionaries

2023-07-18 Thread Paul Moore
On Tue, 18 Jul 2023 at 16:13, Dom Grigonis  wrote:

> To me, they are in the inverse relationship.
>
> Terseness ~ 1 / expressiveness.
>

No, they are unrelated (in general).

Terseness is nothing more than "can I use fewer characters?" and is almost
always the wrong thing to do in isolation (yes, if things get *yoo* verbose
they can be hard to comprehend, but that's about going to extremes, not
about terseness as such).

Expressiveness is about matching the *concepts* involved to the problem. So
list comprehensions are expressive because they declaratively say what the
content of the list should be, and avoid the unnecessary concepts around
how you build the list. It's irrelevant how many characters are involved,
what matters is that you can omit saying "first create an empty list, now
add elements like  one by one..."

Paul
___
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/JMTRAR3HQZL6G7DQHPLSTCGCFFYHFVAA/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal for get_or function in Python dictionaries

2023-07-18 Thread Dom Grigonis
To me, saying it’s about expressiveness but not brevity sounds similar to e.g. 
“we are in compliance with green policies of EU, but we are not making effort 
to save nature.”

Well, you might not consciously intend to save nature, but those who gave you 
presentation about green legislation had that intent, but used fancy words so 
it sounds cooler. Well, saving nature is at least one of major factors, other’s 
being someone profiting from it, other political implications etc...

I might be completely wrong here, some simple and clear emphasis of how they 
are unrelated is welcome.

> On 18 Jul 2023, at 18:11, Dom Grigonis  wrote:
> 
> To me, they are in the inverse relationship.
> 
> Terseness ~ 1 / expressiveness.
> 
> Maybe I am not getting something.
> 
> But surely if list comprehension took 5 lines to write, it wouldn’t be 
> justifiable? So, even if implicit, brevity and its relation to complexity is 
> always a factor.
> 
>> On 18 Jul 2023, at 17:57, Chris Angelico  wrote:
>> 
>> On Wed, 19 Jul 2023 at 00:55, Dom Grigonis  wrote:
>>> Here I am a bit confused, how is this the case in the language containing 
>>> list comprehensions?
>>> 
>> 
>> Do you understand the difference between expressiveness and terseness?
>> You still seem to be focused on the completely wrong thing here. List
>> comprehensions are not about saving lines, they are about expressing
>> the concept of "build a list from a list".
>> 
>> 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/HES5J5CLNNBHXAKIMIQA5WV43GBI6Q4W/
>> Code of Conduct: http://python.org/psf/codeofconduct/
> 

___
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/2L7DMWBTWD3KO7DLZDKOKLJI3NZILC3Q/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal for get_or function in Python dictionaries

2023-07-18 Thread Dom Grigonis
To me, they are in the inverse relationship.

Terseness ~ 1 / expressiveness.

Maybe I am not getting something.

But surely if list comprehension took 5 lines to write, it wouldn’t be 
justifiable? So, even if implicit, brevity and its relation to complexity is 
always a factor.

> On 18 Jul 2023, at 17:57, Chris Angelico  wrote:
> 
> On Wed, 19 Jul 2023 at 00:55, Dom Grigonis  wrote:
>> Here I am a bit confused, how is this the case in the language containing 
>> list comprehensions?
>> 
> 
> Do you understand the difference between expressiveness and terseness?
> You still seem to be focused on the completely wrong thing here. List
> comprehensions are not about saving lines, they are about expressing
> the concept of "build a list from a list".
> 
> 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/HES5J5CLNNBHXAKIMIQA5WV43GBI6Q4W/
> Code of Conduct: http://python.org/psf/codeofconduct/

___
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/SVT7HQ4BHLUTBC4EMY52OIDL5PXYO7ZH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal for get_or function in Python dictionaries

2023-07-18 Thread Dom Grigonis
> 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.
I am still lost in async space. From my initial benchmarking it seems that the 
complexity that async is introducing hardly justifies itself in performance. In 
other words, if it is done using `async` it’s performance is very similar to 
`gevent`, meaning, that all that hassle doesn’t justify itself in performance 
space, which is one of the major selling points.

If async is done with `yield`, then it could potentially be justified in 
performance-critical applications.

I am not 100% certain about this as I haven't compared everything thoroughly, 
but these were the findings from my initial fairly crude testing.

Am I missing something here?

> 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.
I’d rather not have 2nd yield and have things a bit simpler in that space...

> On 18 Jul 2023, at 17:06, Chris Angelico  wrote:
> 
> On Tue, 18 Jul 2023 at 23:41, Stephen J. Turnbull
>  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 

[Python-ideas] Re: Proposal for get_or function in Python dictionaries

2023-07-18 Thread Chris Angelico
On Wed, 19 Jul 2023 at 00:55, Dom Grigonis  wrote:
> Here I am a bit confused, how is this the case in the language containing 
> list comprehensions?
>

Do you understand the difference between expressiveness and terseness?
You still seem to be focused on the completely wrong thing here. List
comprehensions are not about saving lines, they are about expressing
the concept of "build a list from a list".

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/HES5J5CLNNBHXAKIMIQA5WV43GBI6Q4W/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal for get_or function in Python dictionaries

2023-07-18 Thread Dom Grigonis
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 
>  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 

[Python-ideas] Re: Proposal for get_or function in Python dictionaries

2023-07-18 Thread Chris Angelico
On Tue, 18 Jul 2023 at 23:41, Stephen J. Turnbull
 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/


[Python-ideas] Re: Proposal for get_or function in Python dictionaries

2023-07-18 Thread Stephen J. Turnbull
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 

[Python-ideas] Re: Conditional 1-line expression in python (Dom Grigonis)

2023-07-18 Thread Richard Damon

On 7/18/23 12:03 AM, Dom Grigonis wrote:
Ok, thanks. I think what I am aiming at is that there is a pool of 
suggestions and PEPs that are pointing towards very similar direction 
and I find myself often wandering in the same space, just trying to 
figure out what it exactly is.


It sometimes feels more verbose than it could be for what it is in the 
context of how simple python is to use in general.


I am fully well aware that current if-else expression is not going 
anywhere. Chances that another expression is introduced, which does 
exactly the same thing are close to none.


So I am just gauging if it is a matter of conciseness of existing 
expressions or absence of something that could be there. Conditional 
if-else is just a place where I got to naturally.


Got some useful references to PEPs, python history and opinions. Maybe 
it will become more clear in the future or maybe something new is 
already being worked that is going to fill the gap which I am not 
aware of.


I haven’t even started any proposal myself, I was just following 
e-mail requests and rejected PEPs that were mentioned here. Combined 
it with my own experience and this is where I got to.


Currently seems like it’s a dead end. Decision’s have been made, 
opinions taken into account, but I still have to write either:


a) awkward 1-liner
self.value=  valueif  valueis  not  None  else  DefaultClass()
b) 3 nicely readable lines with 1 unnecessary assignment.
self.value=  value
if  valueis  None:
 self.value=  DefaultClass()


or, changing around:

if value is None:

    value = DefaultClass()

self.value = value


since the assignment is fundamental to the operation of the function, 
that is adding 2 lines to implement an optional default, which isn't 
that much to implement the feature.


it could be simplified to one line as

if value is None: value = DefaultClass()

(I think this is legal but against PEP8)



c) 4 lines, no unnecessary assignments with excellent readability.
if  valueis  None:
 self.value=  DefaultClass()
else:
 self.value=  value

The issue with b) and c) is that if I use those ones, my constructors 
become unbearably long and finally lead to the point where development 
becomes awkward. I would think that for what it does, it shouldn’t be 
more than 1 line. Max - 2. But a) is somewhat awkward. All (well not 
all, just several things) taken into account I ended up at 
inconvenience of `ifelse` expression, which would make a) my natural 
choice in this case. I am not even suggesting to introduce analogous 
`ifelse` with different syntax, just trying to get some ideas, 
references, opinions or alternatives that I don’t know about.

-


Richard Damon

___
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/TLOWSO7GPUPU4XW2GP6OOW3IN2NFVWCA/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Conditional 1-line expression in python (Dom Grigonis)

2023-07-18 Thread Chris Angelico
On Tue, 18 Jul 2023 at 19:02, Dom Grigonis  wrote:
>
> Thank you.
>
> I meant “superset of 671, not 505”…
>
> One question:
>
> def bar(a => None);
> return foo(a)
>
> def foo(a => object()):
> return a
>
> How would I force foo’s default from bar’s call?

That's a known-hard problem. The best way is probably to use *a,**kw
and only pass the args you get, but that doesn't always work.

> Would something like this work?
>
> def foo(a => object() if a is None else a):
> return a

Yyes, but now you're defining that a could be None, so you may as
well go with the classic idiom:

def foo(a=None):
if a is None: a = object()

The point of default argument expressions is that you DON'T need to
accept a fake default.

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/RYMC4J53X6RO7RCBXFYWOYLVKQ3Z64BT/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Conditional 1-line expression in python (Dom Grigonis)

2023-07-18 Thread Dom Grigonis
Thank you.

I meant “superset of 671, not 505”…

One question:
def bar(a => None);
return foo(a)

def foo(a => object()):
return a
How would I force foo’s default from bar’s call?

Would something like this work?
def foo(a => object() if a is None else a):
return a


> On 18 Jul 2023, at 09:45, Chris Angelico  wrote:
> 
> On Tue, 18 Jul 2023 at 16:25, Dom Grigonis  wrote:
>> 
>> Yes, thank you, this would definitely be nice to have.
>> 
>> Although, "A generic system for deferred evaluation has been proposed at 
>> times“ sound better if it was a superset of PEP505. Could you refer me to 
>> any resources about such considered system?
>> 
> 
> Hrm, you'd probably have to scour the archives. It's one of those
> things that comes up periodically and spawns a discussion thread, but
> never really gets to a concrete proposal. The best I can find is this,
> which never even got submitted to the official PEP repository, but
> it's someone's attempt to make something that could potentially become
> one, so it's a start.
> 
> https://github.com/DavidMertz/peps/blob/master/pep-.rst
> 
> The trouble is, it's really REALLY hard to pin down useful semantics
> for deferred evaluation. We already have lambda functions, which cover
> a lot of situations, leaving a lot of uncertainty as to what's being
> handled by this new proposal - and since no proposal ever truly comes
> from a single person, that results in a certain amount of chaos.
> 
> 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/XCX54U7H7QWTGHEHUTHCPERW6LVAOUJT/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Conditional 1-line expression in python

2023-07-18 Thread Dom Grigonis
Maybe could be a part of https://peps.python.org/pep-0463/ 


Maybe if it was more expressive, e.g. covering the case such as you suggesting, 
it would go through?

Also, I still don't see why changing analogous statement order when making 
1-line expressions is a good idea.

E.g. there was a statement:
# Statement
try:
expression1
except Exception:
expression2
except Exception:
expression1
el
finally:
expression6
It’s analogous expression then could be:

val = try expr1() except Exception ? expr2() el finally expr5()

Simple if-else statement would be everything in between <> in both statement 
and expression.

Functional, consistent, expressive, in line with what is already there. Both 
“continue” and “break" would also be used in expressions same place as the 
statement. Maybe something else instead of “?”, but it doesn’t matter much to 
me, “?” would be just fine.

This would also partly cover my “rant” about C’s conditional expression. I.e. 
The order. Which probably has more weight in my aversion than it’s verbosity.

* Now argument that expressions read more naturally in this order raises a 
question "Why then isn’t it the same in statements?”.
* And argument that it’s easier for someone to learn without programming 
background also fails as even they would probably prefer “consistency" as 
opposed to "inconsistency, but 1 part reads like english."

I personally find it easier to learn when I understand and I understand when 
things make sense and follow patterns. Can it be that too much of this is being 
sacrificed for the sake of factors which are not as important?

> On 18 Jul 2023, at 09:08, Stephen J. Turnbull 
>  wrote:
> 
> David Mertz, Ph.D. writes:
> 
>> I think the Python version does the right thing by emphasizing the
>> DEFAULT by putting it first, and leaving the predicate and fallback
>> until later in the expression (right for Pythonic code, not right
>> for other languages necessarily).
> 
> Aside: I think that's true for Pythonic scripting, but in general I
> think you're just as likely to find that it's a genuine choice, and
> that the condition is as interesting as either choice.
> 
> Variation on the theme of conditional expression: I'd often like to
> write
> 
>var = computed() if cond() else break
> 
> or
> 
>var = computed() if cond() else continue
> 
> I wonder if that syntax has legs, or if it's too cute to stand.
> 

___
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/3GBJSOMBDFRQSP7IRK3CHAVF57E57O5Q/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Conditional 1-line expression in python (Dom Grigonis)

2023-07-18 Thread Chris Angelico
On Tue, 18 Jul 2023 at 16:25, Dom Grigonis  wrote:
>
> Yes, thank you, this would definitely be nice to have.
>
> Although, "A generic system for deferred evaluation has been proposed at 
> times“ sound better if it was a superset of PEP505. Could you refer me to any 
> resources about such considered system?
>

Hrm, you'd probably have to scour the archives. It's one of those
things that comes up periodically and spawns a discussion thread, but
never really gets to a concrete proposal. The best I can find is this,
which never even got submitted to the official PEP repository, but
it's someone's attempt to make something that could potentially become
one, so it's a start.

https://github.com/DavidMertz/peps/blob/master/pep-.rst

The trouble is, it's really REALLY hard to pin down useful semantics
for deferred evaluation. We already have lambda functions, which cover
a lot of situations, leaving a lot of uncertainty as to what's being
handled by this new proposal - and since no proposal ever truly comes
from a single person, that results in a certain amount of chaos.

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/BEBXTO5WXYRRPNH2IJMWTMIHGCLUFERL/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Conditional 1-line expression in python (Dom Grigonis)

2023-07-18 Thread Dom Grigonis
Yes, thank you, this would definitely be nice to have.

Although, "A generic system for deferred evaluation has been proposed at times“ 
sound better if it was a superset of PEP505. Could you refer me to any 
resources about such considered system?

> On 18 Jul 2023, at 08:33, Chris Angelico  wrote:
> 
> On Tue, 18 Jul 2023 at 14:07, Dom Grigonis  wrote:
>> PEP505 would solve this nicely, but it only applies to None and would not 
>> apply to say user-defined sentinels and many other cases where permutations 
>> of different conditionals arise.
>> 
> 
> PEP 671 would solve this nicely too.
> 
> 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/R4HVE2MYZT7GJAB6SNKHW6UVC2G4OYYO/
> Code of Conduct: http://python.org/psf/codeofconduct/

___
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/OUYIXJ5ZYQUXJBXR5U554YMKLVU6AAKB/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Conditional 1-line expression in python

2023-07-18 Thread Stephen J. Turnbull
David Mertz, Ph.D. writes:

 > I think the Python version does the right thing by emphasizing the
 > DEFAULT by putting it first, and leaving the predicate and fallback
 > until later in the expression (right for Pythonic code, not right
 > for other languages necessarily).

Aside: I think that's true for Pythonic scripting, but in general I
think you're just as likely to find that it's a genuine choice, and
that the condition is as interesting as either choice.

Variation on the theme of conditional expression: I'd often like to
write

var = computed() if cond() else break

or

var = computed() if cond() else continue

I wonder if that syntax has legs, or if it's too cute to stand.

___
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/WUSUIRQ5XLFSS5JQKI3DYZ7SIDABERKY/
Code of Conduct: http://python.org/psf/codeofconduct/