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

2023-07-19 Thread Stephen J. Turnbull
Dom Grigonis writes:

 > The thing I am not content with (to make it common practice in my
 > coding style) is inconsistencies between a) order of terms
 > and b) functionality, of statements and their analogous
 > expressions.

I think that's reasonable.  But I don't think Python is the language
for that.  There are too much existing contrasts, such as loop vs.
comprehension and conditional statement vs. ternary expression.  Guido
deliberately chose to vary those expression syntaxes from their
statement equivalents.  I don't think there's any ambiguity if you say
that wrapping a compound statement in parentheses creates an
expression with restricted syntax (namely, the statements the syntax
controls become expressions):

(if condition_1: expression_1
 elif condition_2: expression_2
 else: expression_else)

[for element in iterable: if condition: expression(element)]

But Guido (and I think everybody else) thought "N! not *that*!"

 > ??
 >  `Deferred evaluation`, if was to gain traction in a similar manner
 >  as e.g. `annotations` are now experiencing, would cover all of the
 >  cases I was looking at & more.

As Chris was saying earlier, it's at minimum going to take some genius
creativity to "cover all and more", because a closer look at what
people mean by "deferred" shows that in different cases it is
semantically different.  In particular, there are a number of choices
that Chris made in PEP 671 that aren't compatible with several of the
proposals for Deferred objectss, while Deferreds can't give some of
the benefits of the PEP.

I didn't like that PEP then; I was in the camp of "let's get genuine
Deferreds, and use them to cover some of the use cases for PEP 671."
I don't actively want the PEP now.  def-time evaluation of defaults
doesn't catch me and I haven't had trouble teaching it.  The
"if arg is None: arg = Mutable()" idiom is rare enough that I prefer
it to adding syntax to the already complex function prototype.

But if you think it might be a good idea, I encourage you to take a
close look.  For some use cases it's definitely an improvement, and at
least I won't vocally oppose the PEP now -- haven't seen any progress
on "true Deferreds".  Perhaps others' opposition has softened, too.
Adding another proponent is another way to help get it going again.

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


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

2023-07-19 Thread Rob Cliffe via Python-ideas



On 15/07/2023 21:08, Dom Grigonis wrote:
Just to add. I haven’t thought about evaluation. Thus, to prevent 
evaluation of unnecessary code, introduction of C-style expression is 
needed anyways:

1. result = bar is None ? default : bar


The below would have to evaluate all arguments, thus not achieving 
benefits of PEP505.

2. result = ifelse(bar is None, default, bar)



So I would vote for something similar to:

result = bar is None ? default : bar


Where default and bar is only evaluated if needed. Although not to the 
extent as initially intended, it would offer satisfiable solutions to 
several proposals.



Well, default is only evaluated if needed; bar is always evaluated.
What is wrong with the Python equivalent

result = default if bar is None else bar
or if you prefer
result = bar if bar is not None else default

Perhaps you didn't know about this construction?
It does exactly the same as the C version and is more readable.  Or am I 
missing something?

Best wishes
Rob Cliffe___
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/4QBAYBAT6EZFILNS2MCK3D6XW4LNRDZ5/
Code of Conduct: http://python.org/psf/codeofconduct/


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

2023-07-19 Thread Dom Grigonis
I understand.

As I have already said, I am not exactly proposing more terse if-else 
expression. It’s just where I got to going down the path of several PEPs, 
proposals and my own 'struggles’.

My point was more along the lines, that these are the examples, where several 
users and PEP writers think python can be improved. It looked like, having more 
terse ternary expression would get all of these half the way in certain 
dimensions that they improve on. I see that dimensions that I picked up upon 
were not exactly the same ones that were aimed at (at least in PEPs).

What I was aiming at is getting more information and ideas and tried to pin 
point common root between all of them, which seemed to be the same which I, 
myself is battling with, but can't pin-point.

Although, I do no deny, I got a bit sidetracked with ternary expression. :)

Verbosity, although important to me, but is of secondary importance. Well, at 
least in ternary expression itself and number of characters. But, when a simple 
thing such as dealing with default of 1 argument takes 4 lines of code, it does 
bother me.

——
In reality, I do not think changing ternary expression would be worth the buck 
anyway. The thing I am not content with (to make it common practice in my 
coding style) is inconsistencies between a) order of terms and b) 
functionality, of statements and their analogous expressions. If they were 
consistent, in a similar way that I wrote in a previous e-mail, it might do the 
trick.

But even then it wouldn’t cover all the cases that I am looking at. It seems to 
be a bit wider.

——
 `Deferred evaluation`, if was to gain traction in a similar manner as e.g. 
`annotations` are now experiencing, would cover all of the cases I was looking 
at & more.

Maybe it would be a win-win. At the core, python would retain its 
expressiveness (which to me personally is more than sufficient compared to 
other dimensions that are important in the context of how I use python and 
where I aim to get with it), but there would exist "a way" for those who 
want/need to write very logically consistent, optimised and concise code.


Thank you for reply,
DG

> On 19 Jul 2023, at 09:25, Stephen J. Turnbull 
>  wrote:
> 
> Dom Grigonis writes:
> 
>>> 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 don't think of list comprehensions in terms of line count.  I often
> write multiple-line list comprehensions and genexps.  Especially when
> nested or with an 'if' clause,, I often use multiple lines even though
> the whole thing would fit on a single line because I feel it expresses
> the structure better.  Comprehensions and genexps are an especially
> nice context for that, because they are always equipped with
> parentheses, so you are not constrained by the usual rules of
> indentation, and don't need line continuing backslashes.
> 
> Also consider
> 
>for x in list1: list2.append(foo(x))
> 
>list2.extend([foo(x) for x in list1])
> 
> The second form is one character less concise than the former, yet far
> more expressive.  Once genexps were introduced, we could make it one
> character more concise than the for loop with
> 
>list2.extend(foo(x) for x in list1)
> 
> but it's unclear that this is an improvement over the list
> comprehension.  (That's probably due to the facts that I don't use
> genexps that often, and that I think of list.extend as a concatenation
> of lists even though it's documented as taking an iterable.  If most
> people have more facility with genexps than I do, it's a small but
> clear improvement.)
> 
>> I would understand if it was swapped with “bad quality & unreadable
>> 1-liners”.
> 
> That dodges the question of when does a one-liner cross over to "bad
> quality and unreadable", though.
> 
>> 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,
> 
> Well, the word "one-liner" has a history.  "One-liner" is a category
> by that name in the Obfuscated C Contest, and Perl programmers often
> take pride in how much they can accomplish on the command line,
> without starting an editor or interactive interpreter.  Some of us
> old-timers are going to take it the wrong way.  I'm not sure if less
> indoctrinated people would take it to mean "readable and expressive
> structures that are balanced in their brevity versus complexity". :-)
> 
> In any case, whether you intend it or not, making the ternary
> expression more terse would encourage examples of the kind you
> present.
> 
>> 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.
> 
> A Python ternary expression usually takes only part of one 

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

2023-07-19 Thread Stephen J. Turnbull
Dom Grigonis writes:

 > > 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 don't think of list comprehensions in terms of line count.  I often
write multiple-line list comprehensions and genexps.  Especially when
nested or with an 'if' clause,, I often use multiple lines even though
the whole thing would fit on a single line because I feel it expresses
the structure better.  Comprehensions and genexps are an especially
nice context for that, because they are always equipped with
parentheses, so you are not constrained by the usual rules of
indentation, and don't need line continuing backslashes.

Also consider

for x in list1: list2.append(foo(x))

list2.extend([foo(x) for x in list1])

The second form is one character less concise than the former, yet far
more expressive.  Once genexps were introduced, we could make it one
character more concise than the for loop with

list2.extend(foo(x) for x in list1)

but it's unclear that this is an improvement over the list
comprehension.  (That's probably due to the facts that I don't use
genexps that often, and that I think of list.extend as a concatenation
of lists even though it's documented as taking an iterable.  If most
people have more facility with genexps than I do, it's a small but
clear improvement.)

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

That dodges the question of when does a one-liner cross over to "bad
quality and unreadable", though.

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

Well, the word "one-liner" has a history.  "One-liner" is a category
by that name in the Obfuscated C Contest, and Perl programmers often
take pride in how much they can accomplish on the command line,
without starting an editor or interactive interpreter.  Some of us
old-timers are going to take it the wrong way.  I'm not sure if less
indoctrinated people would take it to mean "readable and expressive
structures that are balanced in their brevity versus complexity". :-)

In any case, whether you intend it or not, making the ternary
expression more terse would encourage examples of the kind you
present.

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

A Python ternary expression usually takes only part of one line.  They
allow you to put a simple conditional in the middle of a longer
expression.  However, they're not amenable to nesting ternaries,
except in very special circumstances.  I think that's a good thing,
you don't.  We can both be right, you know!  I'm just trying to
explain why I think that way, and making the claim (which may be
incorrect) that the Pythonistas who influence language design do, too.

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

To my eye, that's a great example of "concise but not expressive".
Parsing it requires reading almost character by character, the nuance
of the conditional changes from "True => usual case" to a genuine
choice, and verifying the correctness of the expression is nontrivial
compared to verifying the if statement form.

 > I think the place I am coming from is more about balance than
 > brevity.

OK.  But for me that's hard to see when it's expressed by counting
lines.

Balance and nuance sometimes can be expressed in words, but in cases
where the line is hard to draw, we often go through a large corpus and
find as many examples as possible and compare the existing code with
versions using the new syntax.  Typically it's the stdlib, but since
you mention numerical analysis, numpy or something based on it like
pandas might provide better examples for you.  I don't recommend that
here.  The existence of a semantically equivalent ternary expression
already makes that an impossible lift.

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