Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Steven D'Aprano
On Thu, Apr 26, 2018 at 08:48:12AM -0700, Łukasz Langa wrote:
> 
> > On Apr 25, 2018, at 11:10 PM, Steven D'Aprano  wrote:
> > Criticising binding- 
> > expressions for that reason, especially implying that we must always use 
> > parens, is simply FUD.
> 
> The PEP has more examples with parentheses than without.

Yes? Parens aren't mandatory, and my point that other operators also 
sometimes needs parens still holds.


> >> As soon as we have to wrap a part of an expression in parentheses, 
> >> parsing the entire thing becomes more complex.
> > 
> > Unless it becomes less complex to read and understand.
> 
> You're ignoring the context of the discussion. The new parentheses are 
> there because there's a new assignment there. That's more complex.

I'm not ignoring the context of the discussion. I'm comparing binding- 
expression with and without parens. That's what I thought you were 
doing.

If that wasn't your intended meaning, then I apologise but please 
understand why I answered the way I did.

I still stand by my argument: parens are not always needed, and even 
when they are not needed, adding them can sometimes make things 
*easier* and *less complex* to read.


[...]
> If you think demonstrating cases where the end result won't be an 
> improvement is picking at straws, then maybe the improvement of PEP 
> 572 is as well.

Any feature can have cases where the end result is worse than not using 
the feature. That *alone* isn't a strong argument against a feature.

Do you have much existing code using binding expressions? Of course not. 
Will you be adding them to code that already exists? Probably not -- you 
can't do so until you are using 3.8 at minimum, and if your code needs 
to be backwards compatible, you can't use it until you've dropped 
support for 3.7 and older. That might not be for five or ten years.

So it is likely that for most people only new code will use this 
feature. It is not reasonable to say that if I have existing code like 
this:

spam = expression
if long_condition_that_takes_up_most_of_the_line == spam or spam:
...

that I'm going to immediately change it to a one-liner:

if long_condition_that_takes_up_most_of_the_line == (spam := expression) or 
spam:
...

and push it over the maximum line width. With or without parentheses. 
Why would I do something so silly? Using binding expressions isn't 
mandatory and most coders don't intentionally do things that make their 
code worse.

And if I wouldn't change existing code and push it over the limit, why 
would I write new code that does it? Especially when there are much 
better alternatives:

if (long_condition_that_takes_up_most_of_the_line 
== (spam:=expression)
or spam):
...


We have a history of adding features that can be abused, but aren't. 
People hardly ever abuse list comps with overly long and complex 
multiple-loop comprehensions:

[... for a in sequence for b in something for c in another for d in 
something_else]

I'm sure we've all seen one or two of those. But it doesn't happen 
enough to matter. Same with if...elif...else chains. People didn't 
immediately run out and replace every single if chain into nested 
ternary if expressions, pushing their lines out to beyond the maximum 
line width:

expression if condition else (expression if condition else (expression if 
condition else (expression if condition else expression)))

Real people don't abuse comprehensions or ternary if enough for us to 
regret adding them to the language. I'm sure that they won't abuse this 
feature either. The Python community simply doesn't have the culture of 
abusing syntax in this way and writing overly dense one-liners, and I 
don't think it is reasonable to say this feature will tip the balance.

It is reasonable to say that *some* code will be made worse by this, 
because there's always *someone* who will abuse syntax. There are those 
who insist on writing list comprehensions for their side-effects:

# return and throw away a list of Nones
[print(item) for item in bunch_of_stuff]

but I don't think this happens enough to make us regret adding 
comprehensions to the language.


-- 
Steve
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Is PEP 572 really the most effective way to solve the problems it's targeting?

2018-04-26 Thread Mike Miller

Sorry all, wasn't specific enough.

By "modern" I mean the last decade perhaps.  New languages that have had a 
chance to look at the older generations and choose their best ideas, while 
leaving behind the rest.


Personally I thought of Swift (Ryan mentioned), Kotlin, Rust, and perhaps Go, 
though Go wasn't focused on breaking new ground outside of ease of concurrency. 
I don't know R or Felix at all, but sound interesting.  Nim is another I'm 
vaguely aware of.  They surely have given some thought to the issue.


One thing that jumped out at me is that most replies here jumped to the question 
of whether they supported assignment-expressions, but that is only one potential 
solution.  To be more clear, I wondered how did they solve "the problem itself?" 
 Was their solution different?  Ryan somewhat alluded to that, but I'd like to 
dig in a bit on that part.


In contrast, in many of the other threads I heard, "C, C++, C#, Java, etc do 
assignment-expressions, they're useful and not so hard to learn."  Ok that's 
reasonable, but where is the industry headed?  Python deferred long enough that 
we don't necessarily have to choose a classic solution.


So, it sounds like many of the new generation of languages are not embracing 
these expressions everywhere but rather letting folks do an assignment right in 
the statement where their use case applies, if, while, maybe comprehensions.  Is 
that accurate?


Looks like I've got some homework to do, haha.

-Mike


On 2018-04-26 17:58, Steven D'Aprano wrote:

What counts as a modern language? Less than five years old? Less than
fifty years old? Are Javascript, Ruby and R modern? They all support
assignment as expressions.

I think Koitlin, Rust and Go prohibit assignment as expressions.

Swift assignment evaluates as Void (equivalent to None in Python, I
guess), so you can use assignment in an expression but it returns
nothing and only operates by side-effect.

As far as type hints go, I think that if you need explicit type hints in
the middle of an expression, it's a bad idea and you ought to pull it
out as a separate statement. That applies regardless of whether that
expression involves binding or not.

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (Looking for) A Retrospective on the Move to Python 3

2018-04-26 Thread Alex Walters
http://pyvideo.org/pycascades-2018/bdfl-python-3-retrospective.html link to 
Guido’s talk, for your convenience

 

From: Python-Dev  On 
Behalf Of Guido van Rossum
Sent: Thursday, April 26, 2018 6:12 PM
To: Brett Cannon 
Cc: Barry Warsaw ; Python-Dev 
Subject: Re: [Python-Dev] (Looking for) A Retrospective on the Move to Python 3

 

Also see my talk at PyCascades and Victor's upcoming talk at PyCon.

 

On Thu, Apr 26, 2018, 12:02 Brett Cannon  > wrote:

 

On Thu, 26 Apr 2018 at 10:19 Barry Warsaw  > wrote:

On Apr 26, 2018, at 09:28, Eric Snow  > wrote:
> 
> On Thu, Apr 26, 2018 at 10:25 AM, Eric Snow   > wrote:
>> In pondering our approach to future Python major releases, I found
>> myself considering the experience we've had with Python 3.  The whole
>> Py3k effort predates my involvement in the community so I missed a
>> bunch of context about the motivations, decisions, and challenges.
>> While I've pieced some of that together over the years now since I've
>> been around, I've certainly seen much of the aftermath.  For me, at
>> least, it would be helpful to have a bit more insight into the
>> history. :)

It would certainly be an interesting document, but I suspect you’ll get a bit 
of the old “ask 3 lawyers and get 5 opinions” kind of response. ;)

As I remember it, there was definitely a feeling like, this would be our only 
chance to clean up some annoying cruft, and rectify some (in hindsight) 
incorrect design decisions made over the years, couple with a healthy dose of 
“we have no idea how to do the bytes/str split in a backward compatible way".  
There was probably a sense that the Python community was just small enough to 
be able to handle such a disruptive change, but wouldn’t ever be so again.  The 
latter is definitely true today, even if the former was overly optimistic.

 

I agree with everything Barry said. There are some lessons in hindsight of how 
we could have handled bytes/str, but it was more of a decision of "really long 
transition versus a short one" -- jokes on us for what "short" became ;) -- 
which we simply won't make ever again.

___
Python-Dev mailing list
Python-Dev@python.org  
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/guido%40python.org

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Tim Peters
[Zero Piraeus]
>> Since it now looks like it really *does* have a decent chance, and
>> maybe another -1 has a small chance of tipping the balance: my
>> reaction to the proposal is also emotional. Visceral, in fact, to the
>> extent that I'd aim to read and write less Python if it became
>> commonplace.

[Steven D'Aprano ]
> Funnily enough, that's what some people said about decorator syntax,
> ternary if, type annotations and list comprehensions.
>
> All of them have become great additions to the language.
>
> I hated the idea of aping C and adding += operators and swore I'd never
> use them. That lasted, well, about a month.
>
> Just sayin'.

Well - I've come to respect your opinion, so ... OK, I'll give += a
try.  Frankly, I've grown tired of editing it out of all the packages
I download anyway ;-)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] The new and improved PEP 572, same great taste with 75% less complexity!

2018-04-26 Thread Tim Peters
[Larry Hastings ]
>>> I hate to be pedantic--there's enough of that going on in this thread--but I
>>> can't agree with the word "simplifed" above.  I agree that the code using
>>> binding expressions is shorter.  But considering that emit the two code
>>> examples implement the exact same algorithm, to the point where their
>>> bytecode would look nearly* identical, ISTM that the two code examples are
>>> of identical complexity.

[Tim]
>> In the absence of defining an objectively computable complexity
>> measure,  I expect you're doomed to arguing taste.

[Larry]
> As are you!

I didn't claim otherwise.

> I haven't seen any arguments that binding expressions allow us
> to express programs that were inexpressible in Python before.

They don't.

> I'm not even sure that binding expressions fall under the heading
> of "syntactic sugar", given their negligible semantics (and, imo,
> negligible benefit).  What else is left, on both sides of the debate,
> if not a debate over aesthetics?

I prefer to look at effects on real code.  Other people prefer to philosophize.


>>  For example, argue that both spellings have the same formal
>> "cyclomatic complexity" measure (which they do).  By other formal
>> measures (e.g., total number of identifier instances), the latter
>> spelling is "objectively simpler".  By yet others (e.g., total number
>> of non-whitespace characters divided by total number of lines), the
>> former spelling is "objectively simpler".

> What is this "objective simplicity" measurement you cite?

There are many ways you can (and various programs do) attempt to
define, quantitatively, what "program complexity" means.  Under any
such objectively defined measure, two pieces of code can be
"objectively compared".  I use scare quotes with their ordinary
meaning:  that it's "objective" only if you're silly enough to believe
that _whatever_ numbers you're computing are going to settle the issue
;-)

> I understand that the code example cited had fewer identifiers, so when
> measuring "number of identifiers used" in isolation, the code example using
> binding expressions had fewer of them.

Then you necessarily agree that _if_ our objective definition of
complexity is "total number of identifier instances", the
binding-expression version is "objectively simpler".  It's been
reduced, by definition, to a question of determining which of two
integers is smaller.

> But this is so narrow as to be almost meaningless.

Of course!  As is your original claim that "the two code examples are
of identical complexity". "because" "their bytecode would look nearly
identical".  Well, sure, _if_ that's how we define program complexity,
the conclusion follows.  But there's no reason I can see to accept
that definition to begin with either.  I suspect _you_ like it
primarily because you found it supported the conclusion you had
already reached ;-)

> Perhaps I'm misunderstanding you, but I read this as saying that there's a
> larger, well-established concept called "objective simplicity", of which
> this measurement is a part.  Can you tell me more about it?  Google was no
> help here.

The metrics I mentioned are used by a number of programs that claim to
quantify program complexity.  For example, among many other things,
this program computes cyclomatic complexity, and uses N_2 for "total
number of operands" (which I called "identifiers" instead to
specialize it to the specific example) under the widely used "Halstead
Metrics":

http://radon.readthedocs.io/en/latest/intro.html

My favorite part is where the numerator of the "Maintainability Index" adds in

50 * sin(sqrt(2.4 * C))

where "C is the percent of comment lines (important: converted to
radians)".  WTF?! ;-)  But they're not joking:  some people take this
stuff very seriously.


>> But that all kinda misses the point to me:  the latter spelling is
>> "obviously simpler" in a way that _actually matters_, for the same
>> reason, e.g., a case statement with N cases is "obviously simpler"
>> than the semantically equivalent spelling using N nested if/else
>> if/else if/else if/else ... blocks.

> As I already mentioned, the with-binding-expressions code expresses the same
> code, the same concept, and likely results in the same bytecode, as the
> without-binding-expressions code.

And as I already explained in some detail, while I agree with (almost)
all that, it leaves me cold as a dead fish.  The test-action pairs in
the code are _semantically_ peers, not a nesting of subordinates.
It's _clearer_ to human eyes if the syntactic structure of the code
reflects the peer relationship directly.  I couldn't care less that
the byte code turns out being nearly the same.  I'm not a PVM - I need
to _reason_ about the code I read.  In failing to visually reflect the
peer relationship, the original code obscures a key simplicity.

> In contrast, a switch statement is simpler than a series of nested if
> statements.  It's a different code 

Re: [Python-Dev] Is PEP 572 really the most effective way to solve the problems it's targeting?

2018-04-26 Thread INADA Naoki
On Fri, Apr 27, 2018 at 10:52 AM Paul G  wrote:

> Rust has a few syntactic ways to accomplish the same thing, though. I
think match expressions are used for the equivalent of conditionals that
carry the condition value into the body of the expression, and all blocks
return the result of the last statement, so you can do things like:

> let mut x;
> while { x = foo(); x } {
> bar(x);
> }


Go is similar to Python; it's doesn't allow assignment in expression.
And Go has similar syntax like above;

for x := foo(); x {
 bar(x)
}
if err := baz(); err != nil {
 return err
}

I like Go and I think this syntax can be ported to Python.
But it help only if/while statements.  It doesn't help list comprehension.
And Go doesn't have list comprehension.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Is PEP 572 really the most effective way to solve the problems it's targeting?

2018-04-26 Thread Paul G
Rust has a few syntactic ways to accomplish the same thing, though. I think 
match expressions are used for the equivalent of conditionals that carry the 
condition value into the body of the expression, and all blocks return the 
result of the last statement, so you can do things like:

let mut x;
while { x = foo(); x } {
 bar(x);
}

I don't know if that's idiomatic Rust (and I wrote it on a phone and didn't 
check to be sure it compiles), but it does more or less solve the problem of 
assignment in a control flow condition.

On April 27, 2018 12:58:16 AM UTC, Steven D'Aprano  wrote:
>On Thu, Apr 26, 2018 at 09:36:48AM -0700, Mike Miller wrote:
>
>> However, there were two good questions in this message which I
>haven't seen 
>> addressed yet:
>> 
>> - How are other modern languages solving this issue?
>> - How does this new construct intersect with typing
>functionality?
>
>What counts as a modern language? Less than five years old? Less than 
>fifty years old? Are Javascript, Ruby and R modern? They all support 
>assignment as expressions.
>
>I think Koitlin, Rust and Go prohibit assignment as expressions.
>
>Swift assignment evaluates as Void (equivalent to None in Python, I 
>guess), so you can use assignment in an expression but it returns 
>nothing and only operates by side-effect.
>
>As far as type hints go, I think that if you need explicit type hints
>in 
>the middle of an expression, it's a bad idea and you ought to pull it 
>out as a separate statement. That applies regardless of whether that 
>expression involves binding or not.
>
>
>-- 
>Steve
>___
>Python-Dev mailing list
>Python-Dev@python.org
>https://mail.python.org/mailman/listinfo/python-dev
>Unsubscribe:
>https://mail.python.org/mailman/options/python-dev/paul%40ganssle.io
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] The new and improved PEP 572, same great taste with 75% less complexity!

2018-04-26 Thread Mikhail V
On Thu, Apr 26, 2018 at 4:27 PM, Kirill Balunov  wrote:
>
>
> 2018-04-24 18:31 GMT+03:00 Chris Angelico :
>>
>>
>>
>
> Not sure, but if additional motivating examples are required, there is a
> common pattern for dynamic attribute lookup (snippet from `copy.py`):
>
> reductor = dispatch_table.get(cls)
> if reductor:
> rv = reductor(x)
> else:
> reductor = getattr(x, "__reduce_ex__", None)
> if reductor:
> rv = reductor(4)
> else:
> reductor = getattr(x, "__reduce__", None)
> if reductor:
> rv = reductor()
> else:
> raise Error("un(shallow)copyable object of type %s" % cls)
>
> which can with the current `binding expression` syntax simplified to:
>
> if reductor := dispatch_table.get(cls):
> rv = reductor(x)
> elif reductor := getattr(x, "__reduce_ex__", None):
> rv = reductor(4)
> elif reductor := getattr(x, "__reduce__", None):
> rv = reductor()
> else:
> raise Error("un(shallow)copyable object of type %s" % cls)
>

To me this looks more like a motivating example for adding
GOTO statement to Python... Anybody writing a PEP?  :)
And should not the above be wrapped in a function?
(a workaround in abscence of GOTO)

Also, the ELIF is merely an edge case: once you
have something like:

if value :
rv = f(x)
else :
temp = ...
value = f1(temp)
print (value)
if value :
rv = f2(x)
...

then it does not wrap into anything anymore.


Mikhail
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Steven D'Aprano
On Thu, Apr 26, 2018 at 08:00:46PM +0100, Zero Piraeus wrote:

> Since it now looks like it really *does* have a decent chance, and
> maybe another -1 has a small chance of tipping the balance: my
> reaction to the proposal is also emotional. Visceral, in fact, to the
> extent that I'd aim to read and write less Python if it became
> commonplace.

Funnily enough, that's what some people said about decorator syntax, 
ternary if, type annotations and list comprehensions.

All of them have become great additions to the language.

I hated the idea of aping C and adding += operators and swore I'd never 
use them. That lasted, well, about a month.

Just sayin'.


-- 
Steve
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Is PEP 572 really the most effective way to solve the problems it's targeting?

2018-04-26 Thread Steven D'Aprano
On Thu, Apr 26, 2018 at 09:36:48AM -0700, Mike Miller wrote:

> However, there were two good questions in this message which I haven't seen 
> addressed yet:
> 
> - How are other modern languages solving this issue?
> - How does this new construct intersect with typing functionality?

What counts as a modern language? Less than five years old? Less than 
fifty years old? Are Javascript, Ruby and R modern? They all support 
assignment as expressions.

I think Koitlin, Rust and Go prohibit assignment as expressions.

Swift assignment evaluates as Void (equivalent to None in Python, I 
guess), so you can use assignment in an expression but it returns 
nothing and only operates by side-effect.

As far as type hints go, I think that if you need explicit type hints in 
the middle of an expression, it's a bad idea and you ought to pull it 
out as a separate statement. That applies regardless of whether that 
expression involves binding or not.


-- 
Steve
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Is PEP 572 really the most effective way to solve the problems it's targeting?

2018-04-26 Thread Tim Peters
[Mike Miller]
>> - How are other modern languages solving this issue?

[Greg Ewing ]
> In all the languages I can think of that allow assignments in
> expressions, there is only one assignment operator -- a stand
> alone assignment is just a bare assignment expression.

Pretty much so, but I don't know what "modern" means to Mike.  The R
language may set a record for, umm, innovation here:

"""
There are three different assignment operators: two of them have
leftwards and rightwards forms.[1]
"""

So there are 5 assignment operator spellings in R:

=
<-
->
<<-
->>

Note that the link doesn't tell the whole story either; e.g., they
don't all have the same precedence level.  And, in addition to the 5
infix spellings shown above, there are also prefix (looks like a
2-argument function call) spellings.

Back on Earth ;-) , I think it's worth it to point out that only
languages (with assignment expressions) aping C use "=" for assignment
and "==" for equality.  That was a Really Bad Idea that all other (not
aping C) languages I know of avoided.

But I'm not sure any of this is relevant to what Mike meant by "this issue".


> But those languages were all designed that way from the start.
> I'm not aware of any that began by forbidding assignment in
> expressions and then added it later.

Me neither.  It's certainly the case that Guido would not have
designed a language that aped C's poor decision here.  At its very
start, Python used "=" for both assignment and equality testing (and
== was a syntax error).  So I think it's evident that, at the time, he
didn't envision ever adding assignment expressions.


[1] https://www.rdocumentation.org/packages/base/versions/3.5.0/topics/assignOps
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Reserve ':=' for type-inferred variable initialization (was PEP 572)

2018-04-26 Thread Steven D'Aprano
Hi Fatty, and welcome!

On Thu, Apr 26, 2018 at 08:00:55PM +0200, Fatty Morgan wrote:

> The natural interpretation of 'name := expr' is a PEP 526
> type-annotated variable initialization 'name : T = expr' with the
> type annotation T omitted, the tokens ':' and '=' coalesced, and
> the implied type T inferred as 'type(expr)'.

I'm not sure why you say that is the "natural" interpretation, 
unless you're saying that Guido, Chris, myself and dozens of other 
people taking part of this conversation are unnatural, since none of us 
thought of that interpretation *smiles*

The := token is the second most common assignment operator in 
programming languages, behind only = single equals sign. For those of us 
who were raised on Pascal, it is entirely natural to use = for equality 
tests and := for assignment, and languages that use == for equality are 
the ones which are weird.

Since type-annotations are still only used by a small proportion of 
Python code and Python developers, I doubt that they will jump to the 
interpretation of "explicit type hint with no type given".

If the type-checker can infer the type of the expression, there's no 
need to use the colon at all.

name := expression  # can infer type here
name = expression  # why not just infer the type here?

So using : Type without the type is entirely unnecessary. The colon is 
only needed when you have to specify a type manually.

Your comments about some entirely hypothetical "Python with enforced 
static typing" are interesting but so blue-sky that I honestly doubt 
that there's any point in discussing them now. We're focused on Python 
3.8 and 3.9, not Python 5 or Python 6.


-- 
Steve
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] The new and improved PEP 572, same great taste with 75% less complexity!

2018-04-26 Thread Larry Hastings



On 04/26/2018 12:12 PM, Tim Peters wrote:

[Larry Hastings ]

I hate to be pedantic--there's enough of that going on in this thread--but I
can't agree with the word "simplifed" above.  I agree that the code using
binding expressions is shorter.  But considering that emit the two code
examples implement the exact same algorithm, to the point where their
bytecode would look nearly* identical, ISTM that the two code examples are
of identical complexity.

In the absence of defining an objectively computable complexity
measure,  I expect you're doomed to arguing taste.


As are you!  I haven't seen any arguments that binding expressions allow 
us to express programs that were inexpressible in Python before.  I'm 
not even sure that binding expressions fall under the heading of 
"syntactic sugar", given their negligible semantics (and, imo, 
negligible benefit).  What else is left, on /both/ sides of the debate, 
if not a debate over aesthetics?




   For example, argue
that both spellings have the same formal "cyclomatic complexity"
measure (which they do).  By other formal measures (e.g., total number
of identifier instances), the latter spelling is "objectively
simpler".  By yet others (e.g., total number of non-whitespace
characters divided by total number of lines), the former spelling is
"objectively simpler".


What is this "objective simplicity" measurement you cite?  I understand 
that the code example cited had fewer identifiers, so when measuring 
"number of identifiers used" in isolation, the code example using 
binding expressions had fewer of them.  But this is so narrow as to be 
almost meaningless.


Perhaps I'm misunderstanding you, but I read this as saying that there's 
a larger, well-established concept called "objective simplicity", of 
which this measurement is a part.  Can you tell me more about it?  
Google was no help here.




But that all kinda misses the point to me:  the latter spelling is
"obviously simpler" in a way that _actually matters_, for the same
reason, e.g., a case statement with N cases is "obviously simpler"
than the semantically equivalent spelling using N nested if/else
if/else if/else if/else ... blocks.


As I already mentioned, the with-binding-expressions code expresses the 
same code, the same concept, and likely results in the same bytecode, as 
the without-binding-expressions code.  In contrast, a switch statement 
/is/ simpler than a series of nested if statements.  It's a different 
code construct, it has different (and comparatively restricted) 
semantics, and it results in simpler (and faster) code.  Whereas the 
with-binding-expressions code is equivalent to the 
without-binding-expressions code, semantically, bytecode-ly, etc.  So 
comparing the with-binding-expressions version of the code to the 
simplification afforded by a switch statement isn't an apples-to-apples 
comparison.


In other words: you're really only arguing taste here.  You find it 
"obviously simpler", but this an aesthetic call on your part and not an 
objective measurement.  Me, my tastes are different--I find it 
"needlessly complicated" and prefer the without-binding-expressions version.




If it weren't for that you hate being pedantic, I'd add that you're
overlooking the piles of leading whitespace characters also saved in
the latter ;-)  The number of those saved grows quadratically in the
number of uselessly indented blocks shifted left.


Surely my dislike of being pedantic is irrelevant to your being 
pedantic.  It seems it's not something you mind doing! ;-)


The nightmare scenario of quadratically right-shifted code is of course 
solvable in other ways.  Off the top of my head, one could rewrite the 
code example as follows, without any new syntax:


def r(value):
nonlocal reductor
reductor = value
return value
if r(dispatch_table.get(cls)):
rv = reductor(x)
elif r(getattr(x, "__reduce_ex__", None)):
rv = reductor(4)
elif r(getattr(x, "__reduce__", None)):
rv = reductor()
else:
raise Error("un(shallow)copyable object of type %s" % cls)


It makes this particular code example longer--however it avoids the 
indenting you seem to dislike.  However: given that "r()" is shorter 
than "reductor := ", the more elifs you add, the more overall 
/characters/ you'll save!  With another three or four elifs this version 
would probably use fewer characters overall.


I'm not seriously arguing that people rewrite their code in this way; I 
think it's less clear this way.  I suppose my point is, "we already have 
so many ways To Do It, I'm not in favor of adding syntax to the language 
to add one more way".




and the density of complexity per line has shot up.

Average non-whitespace character count per line has certainly shot up,
but I don't actually know what you mean by "density of complexity"
there.


What I meant was, stuff-accomplished-per-line.  I guess we could measure 
that 

Re: [Python-Dev] Is PEP 572 really the most effective way to solve the problems it's targeting?

2018-04-26 Thread Greg Ewing

Mike Miller wrote:

- How are other modern languages solving this issue?


In all the languages I can think of that allow assignments in
expressions, there is only one assignment operator -- a stand
alone assignment is just a bare assignment expression.

But those languages were all designed that way from the start.
I'm not aware of any that began by forbidding assignment in
expressions and then added it later.

--
Greg

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 394 update proposal: Allow changing the `python` command in some cases

2018-04-26 Thread Ben Finney
Petr Viktorin  writes:

> In Fedora, I found that PEP 394's strict recommendation that `python`
> points to `python2` is holding us back.

I have read the message, but I don't see how you draw the link that PEP
394 is holding you back.

> The problems are:
> - For developers that are not following the language's development,
> the fact that `python` invokes `python2` sends a strong signal that 2
> is somehow the preferred version, and it's OK to start new projects in
> it.

I agree with the statement you make later in the message:

> […] we feel that the only way to *enforce* that guidelines is to
> provide environments where the `python` command does not work (unless
> explicitly installed).

Yes. The ‘python’ command is confusing, for the reasons you say. There
should be ‘python2’ and ‘python3’ commands for Python 2 and Python 3
respectively, and no ‘python’ command should be installed by the
operating system.

The fact that ‘/usr/bin/python’ exists is an historical accident, and I
agree with the proposal you state: the best way to correct the confusion
is to bar the confusing command from being installed by packages.

> - Users and sysadmins that *do* want to “live in the future” are
> switching the symlink to `python3` themselves. We would like to give
> them a supported, documented way to do so -- and make surer they're
> aware of the caveats.

The supported, documented way to add a command pointing to a different
command already exists, and there is no need to make a Python-specific
special case.

Users who want to make a ‘python’ alias can do so in their shell; this
is supported and documented.

Users who want to add a new command file can add a suitable directory
(e.g. ‘$HOME/bin’) to their ‘PATH’ variable, and put a symlink in there
named ‘python’. This is supported and documented.

Sysadmins who want to create a system-wide command ‘python’ can put a
symlink at ‘/usr/local/bin/python’. This is supported and documented.

I disagree with making some special-case extra way; that would be both
cunfusing and superfluous.

> - The `python` command is still not available out-of-the box on macOS,
> so it didn't completely live up to the expectation of being the
> cross-platform way to launch 2/3 source compatile scripts.

That is one of the minor ways which macOS fails to conform to
community-agreed conventions. We should not let that intransigence
distort our discussion of best practices.

> To help solve these, I would like to relax recommendations on the Unix
> ``python -> python2`` symlink in these cases:

For the above reasons, I disagree that PEP 394 is limiting what you want
to do on free-software operating systems.

For non-free operating systems, I don't think the already-discussed PEP
394 should be weakened if the operating system vendor fails to conform.

> - Users and administrators can, by a deliberate action, change
> ``python`` to invoke Python 3.

Yes. That is well-known and long-standardised on Unix operating systems,
and is much more broadly understood than any Python-specific special
case would be. So I don't see how anyone is being held back.

I trust that PEP 394 will not be weakened in its effect, and I wish you
well with using the already-supported, already-documented, PEP-394
compatible means to add local customisations for a ‘python’ command.

-- 
 \  “Pity the meek, for they shall inherit the earth.” —Donald |
  `\  Robert Perry Marquis |
_o__)  |
Ben Finney

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 572: Why not := as standard assignment operator?

2018-04-26 Thread Greg Ewing

Chris Angelico wrote:

No. Any expression may be used as a statement, so this isn't "outside
an expression".


It could be detected as a special case and rejected some
time later in the compilation process. The question is
whether it's worth making the rules more complicated just
to forbid something that some peple think is bad style.

--
Greg
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (Looking for) A Retrospective on the Move to Python 3

2018-04-26 Thread Guido van Rossum
Also see my talk at PyCascades and Victor's upcoming talk at PyCon.

On Thu, Apr 26, 2018, 12:02 Brett Cannon  wrote:

>
>
> On Thu, 26 Apr 2018 at 10:19 Barry Warsaw  wrote:
>
>> On Apr 26, 2018, at 09:28, Eric Snow  wrote:
>> >
>> > On Thu, Apr 26, 2018 at 10:25 AM, Eric Snow <
>> ericsnowcurren...@gmail.com> wrote:
>> >> In pondering our approach to future Python major releases, I found
>> >> myself considering the experience we've had with Python 3.  The whole
>> >> Py3k effort predates my involvement in the community so I missed a
>> >> bunch of context about the motivations, decisions, and challenges.
>> >> While I've pieced some of that together over the years now since I've
>> >> been around, I've certainly seen much of the aftermath.  For me, at
>> >> least, it would be helpful to have a bit more insight into the
>> >> history. :)
>>
>> It would certainly be an interesting document, but I suspect you’ll get a
>> bit of the old “ask 3 lawyers and get 5 opinions” kind of response. ;)
>>
>> As I remember it, there was definitely a feeling like, this would be our
>> only chance to clean up some annoying cruft, and rectify some (in
>> hindsight) incorrect design decisions made over the years, couple with a
>> healthy dose of “we have no idea how to do the bytes/str split in a
>> backward compatible way".  There was probably a sense that the Python
>> community was just small enough to be able to handle such a disruptive
>> change, but wouldn’t ever be so again.  The latter is definitely true
>> today, even if the former was overly optimistic.
>>
>
> I agree with everything Barry said. There are some lessons in hindsight of
> how we could have handled bytes/str, but it was more of a decision of
> "really long transition versus a short one" -- jokes on us for what "short"
> became ;) -- which we simply won't make ever again.
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/guido%40python.org
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Kirill Balunov
2018-04-26 13:20 GMT+03:00 Steve Holden :

> On Thu, Apr 26, 2018 at 8:56 AM, Steven D'Aprano 
> wrote:
>
>> On Thu, Apr 26, 2018 at 03:31:13AM -0400, Terry Reedy wrote:
>> > On 4/25/2018 8:20 PM, Chris Angelico wrote:
>> > >On Thu, Apr 26, 2018 at 10:11 AM, Yury Selivanov
>> > > wrote:
>> > >>Just yesterday this snippet was used on python-dev to show how great
>> the
>> > >>new syntax is:
>> > >>
>> > >>   my_func(arg, buffer=(buf := [None]*get_size()),
>> size=len(buf))
>> >
>> > What strikes me as awful about this example is that len(buf) is
>> > get_size(), so the wrong value is being named and saved.
>> > 'size=len(buf)' is, in a sense, backwards.
>>
>> Terry is absolutely right, and I'm to blame for that atrocity. Mea
>> culpa.
>>
>> ​Perhaps a better spelling would be
>
> my_func(arg, buffer=[None]*(buflen := get_size()), size=buflen)
>
>
I know it is non productive and spamy (I promise, this is the last)  since
`as` syntax is dead. In many cases, there is not much difference in
perception between `:=` and `as`. But in several situations, like this one
and as Ethan pointed up-thread - the expression first syntax makes obvious
the intent and linearly readable:

my_func(arg, buffer=[None]*get_size() as buf, size=buf)


In any case, it is rather an anti-pattern than a good example to follow.

p.s.: as Victor Stinner wrote on twitter that previously, there was a
similar PEP in spirit - "PEP 379 -- Adding an Assignment Expression", which
was withdrawn. May be it is worth to make a link to it in the current PEP.


With kind regards,
-gdg
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Tim Peters
[Tim]
>> So, to match your sarcasm, here's mine:  try using a feature for what
>> it's good at instead of for what it's bad at ;-)

[Lukasz Langa ]
> Yes, this is the fundamental wisdom.  Judging which is which is left as an
> exercise to the programmer.
>
> With this, I'm leaving the discussion.  With Guido and you on board for PEP
> 572, I feel that Chris' streak is indeed about to break.

I still expect it could go either way, but do wish people didn't
believe it will be a major loss if "the other side wins".  I'll be
fine regardless - and so will everyone else.  Guido rarely makes
language design mistakes.  In this case he's seeing serious opposition
from several core developers, and you shouldn't believe either that he
just dismisses that.


 [Łukasz Langa]
>>> Well, you have an entire code style built around this feature called Yoda
>>> conditions. You teach people on Day 1 to never ever confuse == with =. Some
>>> compilers even warn about this because so many people did it wrong.

>> Sorry, I couldn't follow that.

Part of the problem here is that I had never seen "Yoda conditions"
before, and had no idea what it meant.  Some later Googling suggests
it's "a thing" youngsters say at times ;-)


> You implied that newbies don't have to even know about assignments in
> expressions.  I wanted to demonstrate that this isn't really the case because
> mistaking `=` for `==` is a relatively common occurence for newbies.  If you
> want to argue that it isn't, I'd like to point out that the WordPress code
> style *requires* Yoda conditions because it was enough of a hindrance.  ESLint
> (a JavaScript linter) also has a warning about assignment in a conditional.

What does that have to do with Python?  If they try to use "=" in an
expression now, they get a SyntaxError.  The PEP doesn't change
anything about that.  Indeed, that's why it uses ":=" instead.  I have
experience in other languages with embedded assignments that also use
":=", and it's _never_ the case that people type ":=" when they intend
"equality test" in those.  The horrid "I typed = when I meant =="
mistakes are unique to languages that mindlessly copied C.  The
mistakes aren't primarily due to embedded assignments, they're due to
that even highly experienced programmers sometimes type "=" when
they're _thinking_ "equals".  Nobody types ":=" when they're thinking
"equals".


> ...
> What you're saying is true.  But for it to be true, newbies *have to* learn 
> the
> distinction, and the fact that yes, sometimes the programmer indeed meant to
> put a single `=` sign in the conditional.

Again, the PEP is about Python:  a single "=" in a conditional is, and
will remain, a SyntaxError.  So nobody can sanely intend to put a
single "=" in a condition _in Python_ unless they're writing a test
intending to provoke a syntax error.


> That's why we'll end up with the Pascal assignment operator.

":=" is already in the PEP.


>  And that *is* a thing that you will have to explain to newbies when they 
> encounter
> it for the first time.

Sure.  That doesn't frighten me, though.  It's easy to explain what it
does - although it may be hard to explain when it's _desirable_ to use
it.


> Sadly, googling for a colon followed by an equal sign isn't trivial if you 
> don't
> know what you're looking for.

To judge from Stackoverflow volume, the single most misunderstood of
all Python operators - by far - is "is" - try Googling for that ;-)
In far second and third places are "and" and "or", for which searches
are also useless.

Regardless, I'm not concerned about one-time tiny learning curves.
Don't know what ":=" means already?  Ask someone.  If you know what
"=" means, you're already close to done.  Given that you already
understand what "binding a name" means, ":=" may well be the simplest
of all Python's operators (there's no computation _to_ be understood,
and no possibility either of a dunder method changing its meaning
depending on operand type(s)).


>>> Well, you can also use it as a statement. But don't!

>> Why not?  _Every_ expression in Python can be used as a statement.
>> Nothing forbids it, and that's even (very!) useful at an interactive
>> prompt.

> Because it suggests different intent, because it's limited, because it's 
> slower
> at runtime, and because PEP 572 says so itself.

I didn't say you're _required_ to use it as a statement.  Regardless
of what PEPs say, people will do what they find most useful.  I trust
people to figure this out quickly for themselves.


>> At this point I think you must have a lower opinion of Python
>> programmers than I have ;-)  If adding even a dozen characters to a
>> line makes it exceed a reasonable line-length guide, the code was
>> almost certainly too confusingly dense to begin with.

> Around 5% of if and elif statements in the standard library don't fit a single
> line *as is*.  Sure, that's a low percentage but that's over 1,000 statements.
> If you're putting an `if` 

[Python-Dev] Nickname Binding (PEP 572)

2018-04-26 Thread Jim J. Jewett
I think part of the disconnect is that this enhancement could very
easily be abused, and it seems likely that it will be, because the
problems aren't visible while writing the code -- only when reading it
later.

I therefore suggest making it very clear in the PEP -- and probably in
PEP 8 --  how these expressions should be limited.  Simply renaming
them to "nickname binding" would be start, but here is a rough draft
for wording.



When scanning code by eye, it is helpful that assignments are (almost)
always at the start of a line.  Even def and class statements can
cause confusion if the reader didn't realize that the name referred to
a class, rather than an instance.  Moving assignments to the middle of
a line will make it harder for someone else to read your code -- so
don't do that.

A nickname is just a regular name, except that it also suggests an
intimate environment.  If the name is purely for documentation, or
will be used only later in the same expression (or, possibly, the same
block or just after), then a nickname may be appropriate.  But

*  If you are wondering what to do about type hints, then the
expression is probably too complex to leave inline.  Separate it out
into a regular assignment statement; nicknames do not support type
hints.

*  If you will be saving the value -- even as an attribute on self --
there is a chance it will be retrieved in a very different context.
Use a regular assignment statement; nicknames are just simple names,
not attributes or keys.

*  If you will be using the value somewhere else in your code, use a
regular assignment statement.  This makes it easier to find, and warns
people that the value may be used again later.

-jJ
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 572: Why not := as standard assignment operator?

2018-04-26 Thread Terry Reedy

On 4/26/2018 11:38 AM, Gustavo Carneiro wrote:


On Thu, Apr 26, 2018 at 11:13 PM, Martin Teichmann
> wrote:
> when reading PEP 572 I actually liked it a lot - I think it's actually
> a cool idea. I think it's actually that cool an idea that it should be
> made the default way of doing an assignment, over time phasing out the
> good ole =.


Please no, I really, really appreciate not having to see add ':' all the 
time.  Plus, it already has two other uses: end of header and dict 
key-item separator.  Plus, see below.


In the interest of that, do you think := can be made illegal, by the 
grammar, if used outside an expression?


a = 1  # legal
a := 1  # Syntax error
if a := 1:  # legal


Please no.

PEP 572 does not discuss top-level interactive assignments.  But it 
should, because having two forms of assignment that lets one choose to 
echo or not is a plus.


Sometimes one wants to see the result of an assignment.  After

>>> a, b = 14387, 344

it would be nice to be able to write

>>> diff := a - b
14343

instead of

>>> diff = a - b
>>> diff
14343

I consider this a significant positive feature of the proposal.

On the other hand, sometimes one does not want the see the result.  A 
long result is often useless to view and may scroll previous results out 
of the window.  A very long result may scroll previous results out of a 
finite console buffer altogether.  (For Windows Command Prompt, the 
default is 300 lines, with a max of .)


And sometimes the result must not be printed.  Tk text widgets (and 
hence IDLE's Shell) do not have a particular limit on the number of 
lines.  On the other hands, long lines drasticly slow down a text 
widget, and a long enough line will freeze it.  (This is supposed to be 
fixed in Tcl/Tk 8.7, now in a1 stage.)  For instance, ">>> 
[None]*100" in IDLE freezes the process.


--
Terry Jan Reedy


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Boundaries between numbers and identifiers

2018-04-26 Thread Serhiy Storchaka

26.04.18 22:02, Lukasz Langa пише:

On Apr 26, 2018, at 11:37 AM, Serhiy Storchaka  wrote:

I propose to change the Python syntax by adding a requirement that there should 
be a whitespace or delimiter between a numeric literal and the following 
keyword.

-1

This would make Python 3.8 reject code due to stylistic preference. Code that 
it actually can unambiguously parse today.


Of course I don't propose to make it a syntax error in 3.8. It should 
first emit a SyntaxWarning and be converted into an error only in 3.10.


Or maybe first add a rule for this in PEP 8 and make it a syntax error 
in distant future, after all style checkers include it.



I agree that a formatting style that omits whitespace between numerals and 
other tokens is terrible.  However, if you start downright rejecting it, you 
will likely punish the wrong people.  Users of third-party libraries will be 
met with random parsing errors in files they have no control over.  This is not 
helpful.

And given BPO-8 the standard library tokenizer would have to keep parsing 
those things as is.

Making 0or[] working again is also not worth it since that's been broken since 
Python 2.6 and hopefully nobody is running Python 2.5-only code anymore.

What we should instead is to make the standard library tokenizer reflect the 
behavior of Python 2.6+.


The behavior of the standard library tokenizer doesn't contradict rules. 
It is the most natural behavior of regex-based tokenizer. Actually the 
behavior of the building tokenizer can be incorrect. In any case 
accepting `1if 2else 3` and rejecting `0or[]` looks weird. They should 
use the same rule. "0or" and "2else" should be considered ambiguous or 
unambiguous in the same way.

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Order of positional and keyword arguments

2018-04-26 Thread Paul Moore
I see no practical benefit to making such a restriction, and there's a
risk of breaking existing code.

While it's not something I've ever used myself in real code,

def wrapper(*args, **kw):
return wrapped_fn(some_arg=1, *args, **kw)

seems like a perfectly reasonable way to write a wrapper to me. I'm
against breaking this for no better reason than "to simplify the
grammar" and to exclude cases that some people might find confusing (I
actually found your example perfectly comprehensible, if convoluted).

-1 from me.

Paul


On 26 April 2018 at 20:25, Serhiy Storchaka  wrote:
> There is an inconsistence in passing arguments to functions.
>
> Explicit positional arguments should precede keyword arguments (both
> explicit and variable), but variable positional arguments can follow
> explicit keyword arguments and precede variable keyword arguments.
>
> For example, for function
>
> def f(a=None, b=None):
> return a, b
>
> the following is valid syntax:
>
> f(1, b=2)
> f(1, **{'b': 2})
> f(*[1], b=2)
> f(*[1], **{'b': 2})
> f(b=2, *[1])
>
> but the following is an error:
>
> f(b=2, 1)
> f(**{'b': 2}, 1)
> f(**{'b': 2}, *[1])
>
> f(b=2, *[1]) is surprised in two ways:
>
> 1. Argument values are passed not in order. The first value is assigned to
> the second parameter, and the second value is assigned to the first
> parameter.
>
> 2. Argument values are evaluated not from left to right. This contradicts
> the general rule that expressions are evaluated from left to right (with few
> known exceptions).
>
> I never seen the form `f(b=2, *[1])` in practice (though the language
> reference contains an explicit example for it), and it looks weird to me. I
> don't see reasons of writing `f(b=2, *[1])` instead of more natural `f(*[1],
> b=2)`. I propose to disallow it.
>
> This will also make the grammar simpler. Current grammar:
>
>argument_list: `positional_arguments` ["," `starred_and_keywords`]
> :   ["," `keywords_arguments`]
> : | `starred_and_keywords` ["," `keywords_arguments`]
> : | `keywords_arguments`
>positional_arguments: ["*"] `expression` ("," ["*"] `expression`)*
>starred_and_keywords: ("*" `expression` | `keyword_item`)
> : ("," "*" `expression` | "," `keyword_item`)*
>keywords_arguments: (`keyword_item` | "**" `expression`)
> : ("," `keyword_item` | "," "**" `expression`)*
>keyword_item: `identifier` "=" `expression`
>
> Proposed grammar:
>
>argument_list: `positional_arguments` ["," `keywords_arguments`]
> : | `keywords_arguments`
>positional_arguments: ["*"] `expression` ("," ["*"] `expression`)*
>keywords_arguments: `keyword_argument` ("," `keyword_argument`)*
>keyword_argument: `identifier` "=" `expression` | "**" `expression`
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/p.f.moore%40gmail.com
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Order of positional and keyword arguments

2018-04-26 Thread Serhiy Storchaka

There is an inconsistence in passing arguments to functions.

Explicit positional arguments should precede keyword arguments (both 
explicit and variable), but variable positional arguments can follow 
explicit keyword arguments and precede variable keyword arguments.


For example, for function

def f(a=None, b=None):
return a, b

the following is valid syntax:

f(1, b=2)
f(1, **{'b': 2})
f(*[1], b=2)
f(*[1], **{'b': 2})
f(b=2, *[1])

but the following is an error:

f(b=2, 1)
f(**{'b': 2}, 1)
f(**{'b': 2}, *[1])

f(b=2, *[1]) is surprised in two ways:

1. Argument values are passed not in order. The first value is assigned 
to the second parameter, and the second value is assigned to the first 
parameter.


2. Argument values are evaluated not from left to right. This 
contradicts the general rule that expressions are evaluated from left to 
right (with few known exceptions).


I never seen the form `f(b=2, *[1])` in practice (though the language 
reference contains an explicit example for it), and it looks weird to 
me. I don't see reasons of writing `f(b=2, *[1])` instead of more 
natural `f(*[1], b=2)`. I propose to disallow it.


This will also make the grammar simpler. Current grammar:

   argument_list: `positional_arguments` ["," `starred_and_keywords`]
:   ["," `keywords_arguments`]
: | `starred_and_keywords` ["," `keywords_arguments`]
: | `keywords_arguments`
   positional_arguments: ["*"] `expression` ("," ["*"] `expression`)*
   starred_and_keywords: ("*" `expression` | `keyword_item`)
: ("," "*" `expression` | "," `keyword_item`)*
   keywords_arguments: (`keyword_item` | "**" `expression`)
: ("," `keyword_item` | "," "**" `expression`)*
   keyword_item: `identifier` "=" `expression`

Proposed grammar:

   argument_list: `positional_arguments` ["," `keywords_arguments`]
: | `keywords_arguments`
   positional_arguments: ["*"] `expression` ("," ["*"] `expression`)*
   keywords_arguments: `keyword_argument` ("," `keyword_argument`)*
   keyword_argument: `identifier` "=" `expression` | "**" `expression`

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] The new and improved PEP 572, same great taste with 75% less complexity!

2018-04-26 Thread Tim Peters
[Kirill Balunov]
> Not sure, but if additional motivating examples are required, there is a
> common pattern for dynamic attribute lookup (snippet from `copy.py`):
>
> reductor = dispatch_table.get(cls)
> if reductor:
> rv = reductor(x)
> else:
> reductor = getattr(x, "__reduce_ex__", None)
> if reductor:
> rv = reductor(4)
> else:
> reductor = getattr(x, "__reduce__", None)
> if reductor:
> rv = reductor()
> else:
> raise Error("un(shallow)copyable object of type %s" % cls)
>
> which can with the current `binding expression` syntax simplified to:
>
> if reductor := dispatch_table.get(cls):
> rv = reductor(x)
> elif reductor := getattr(x, "__reduce_ex__", None):
> rv = reductor(4)
> elif reductor := getattr(x, "__reduce__", None):
> rv = reductor()
> else:
> raise Error("un(shallow)copyable object of type %s" % cls)
>
> which becomes much clearer, at least in my opinion.

[Larry Hastings ]
> I hate to be pedantic--there's enough of that going on in this thread--but I
> can't agree with the word "simplifed" above.  I agree that the code using
> binding expressions is shorter.  But considering that emit the two code
> examples implement the exact same algorithm, to the point where their
> bytecode would look nearly* identical, ISTM that the two code examples are
> of identical complexity.

In the absence of defining an objectively computable complexity
measure,  I expect you're doomed to arguing taste.  For example, argue
that both spellings have the same formal "cyclomatic complexity"
measure (which they do).  By other formal measures (e.g., total number
of identifier instances), the latter spelling is "objectively
simpler".  By yet others (e.g., total number of non-whitespace
characters divided by total number of lines), the former spelling is
"objectively simpler".

But that all kinda misses the point to me:  the latter spelling is
"obviously simpler" in a way that _actually matters_, for the same
reason, e.g., a case statement with N cases is "obviously simpler"
than the semantically equivalent spelling using N nested if/else
if/else if/else if/else ... blocks.  The latter spelling above is
indeed visually very much like a case statement:  all the tests are at
the same indentation level, and all the conditional actions are too.
It's obvious _at a glance_ in the latter that exactly one of the
action blocks will be performed.  That's how if/elif/elif/else always
works.  It's not at all obvious at a glance (certainly not to me) in
the original spelling.

> Comparing the two, the code using the binding expressions obviates four
> newlines, three uses of the identifier "reductor", and allows folding two
> "else / if"s into "elif"s.  In exchange, it adds three extra colons,

If it weren't for that you hate being pedantic, I'd add that you're
overlooking the piles of leading whitespace characters also saved in
the latter ;-)  The number of those saved grows quadratically in the
number of uselessly indented blocks shifted left.

> and the density of complexity per line has shot up.

Average non-whitespace character count per line has certainly shot up,
but I don't actually know what you mean by "density of complexity"
there.

Just FYI, when I write long if/elif/elif/... chains, I typically put a
blank line before each elif, to give better visual separation of the
peer (both semantically and visually) test-action blocks.  Which has
nothing to do with any formal notion of complexity, because I don't
much care about that - readability is what I value, and that's not the
same as any formal notion of complexity I've ever seen.

>  ...
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Terry Reedy

On 4/26/2018 6:34 AM, Greg Ewing wrote:

Antoine Pitrou wrote:

Well, how do languages where assignment is an expression returning the
assigned value make their REPLs work?  I'm sure they don't inflict that
on their users, so it's certainly a solvable problem.


I can't think of any such language that has a REPL
offhand, but here's a possible solution:


    x := expr # doesn't print anything


Ugh! The only reason I would bother typing the : in a top level 
assignment would be to get the print without having to retype the name, 
as in


>>> x = expr
>>> x

I consider echoing top-level interactive assignments to be a feature of 
the proposal.


--
Terry Jan Reedy


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Boundaries between numbers and identifiers

2018-04-26 Thread Lukasz Langa

> On Apr 26, 2018, at 11:37 AM, Serhiy Storchaka  wrote:
> 
> I propose to change the Python syntax by adding a requirement that there 
> should be a whitespace or delimiter between a numeric literal and the 
> following keyword.

-1

This would make Python 3.8 reject code due to stylistic preference. Code that 
it actually can unambiguously parse today.

I agree that a formatting style that omits whitespace between numerals and 
other tokens is terrible.  However, if you start downright rejecting it, you 
will likely punish the wrong people.  Users of third-party libraries will be 
met with random parsing errors in files they have no control over.  This is not 
helpful.

And given BPO-8 the standard library tokenizer would have to keep parsing 
those things as is.

Making 0or[] working again is also not worth it since that's been broken since 
Python 2.6 and hopefully nobody is running Python 2.5-only code anymore.

What we should instead is to make the standard library tokenizer reflect the 
behavior of Python 2.6+.

-- Ł
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Zero Piraeus
:

On 25 April 2018 at 21:28, Guido van Rossum  wrote:
> A very emotional appeal, you don't seem to grasp the usability improvements
> this will give. I hear you but at this point appeals to Python's "Zen" don't
> help you.

I have to admit, in half-following this discussion I've swung between
thinking "there's no way this is actually going to happen" and "what,
this might actually happen?"

Since it now looks like it really *does* have a decent chance, and
maybe another -1 has a small chance of tipping the balance: my
reaction to the proposal is also emotional. Visceral, in fact, to the
extent that I'd aim to read and write less Python if it became
commonplace.

I don't have arguments. I just have an instinctive "ugh, no".

 -[]z.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (Looking for) A Retrospective on the Move to Python 3

2018-04-26 Thread Brett Cannon
On Thu, 26 Apr 2018 at 10:19 Barry Warsaw  wrote:

> On Apr 26, 2018, at 09:28, Eric Snow  wrote:
> >
> > On Thu, Apr 26, 2018 at 10:25 AM, Eric Snow 
> wrote:
> >> In pondering our approach to future Python major releases, I found
> >> myself considering the experience we've had with Python 3.  The whole
> >> Py3k effort predates my involvement in the community so I missed a
> >> bunch of context about the motivations, decisions, and challenges.
> >> While I've pieced some of that together over the years now since I've
> >> been around, I've certainly seen much of the aftermath.  For me, at
> >> least, it would be helpful to have a bit more insight into the
> >> history. :)
>
> It would certainly be an interesting document, but I suspect you’ll get a
> bit of the old “ask 3 lawyers and get 5 opinions” kind of response. ;)
>
> As I remember it, there was definitely a feeling like, this would be our
> only chance to clean up some annoying cruft, and rectify some (in
> hindsight) incorrect design decisions made over the years, couple with a
> healthy dose of “we have no idea how to do the bytes/str split in a
> backward compatible way".  There was probably a sense that the Python
> community was just small enough to be able to handle such a disruptive
> change, but wouldn’t ever be so again.  The latter is definitely true
> today, even if the former was overly optimistic.
>

I agree with everything Barry said. There are some lessons in hindsight of
how we could have handled bytes/str, but it was more of a decision of
"really long transition versus a short one" -- jokes on us for what "short"
became ;) -- which we simply won't make ever again.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 573 -- Module State Access from C Extension Methods

2018-04-26 Thread Petr Viktorin

On 04/26/18 09:32, Thomas Wouters wrote:


Thanks for working on this, Marcel (and Petr). This looks like an 
ambitious intern project :) Couple of questions and comments in-line.


Indeed, but also a multi-year one. Sometimes it seems like Python is 
moving too fast under us!


Specifically, PEP 573 (Unifying function/method classes) andto a smaller 
extent PEP 567 (Context Variables) seem to be solving similar problems 
as this PEP. I'm inclined to put this PEP temporarily on hold, help 575 
get accepted, and then rebase on top of that.



On Mon, Apr 23, 2018 at 12:36 PM, Marcel Plch > wrote:

PEP: 573

[...]


Abstract



[...]


Additionaly, support for easier creation of immutable exception
classes is added.


I'm not a fan of using 'immutable' here, or in the API function name. I 
understand the types are to some extent immutable (apart from their 
refcount, I assume), but I think it's going to be too easy to confuse it 
with types whose *instances* are immutable. (We do occasionally say 
things like "tuples are an immutable type".) Since the point is that 
they behave like statically defined ones, perhaps 'Static' would be a 
reasonable replacement.


That was the first naming choice, but then on the other hand, "static 
heap type" sounds like an oxymoron -- in C, static things don't live on 
the heap.

Naming is hard :(


[...]

Slot methods


The above changes don't cover slot methods, such as ``tp_iter`` or
``nb_add``.

The problem with slot methods is that their C API is fixed, so we can't
simply add a new argument to pass in the defining class.
Two possible solutions have been proposed to this problem:

     * Look up the class through walking the MRO.
       This is potentially expensive, but will be useful if
performance is not
       a problem (such as when raising a module-level exception).
     * Storing a pointer to the defining class of each slot in a
separate table,
       ``__typeslots__`` [#typeslots-mail]_.  This is technically
feasible and fast,
       but quite invasive.

Due to the invasiveness of the latter approach, this PEP proposes
adding an MRO walking
helper for use in slot method implementations, deferring the more
complex alternative
as a potential future optimisation. Modules affected by this concern
also have the
option of using thread-local state or PEP 567 context variables, or
else defining their
own reload-friendly lookup caching scheme.


I do not believe walking the MRO is going to work without reworking the 
implementation of types, specifically how typeobject.c deals with slots 
of subclasses: in some cases copies the slots from the base class (see 
inherit_slots() and from where it's called). I believe this would cause 
problems if, for example, you define type X in module A, subclass it 
from type Y in module B without overriding the slot, and try to find the 
module object for A from the slot implementation. I don't think copying 
slots is a requirement for the desired semantics, but it's going to be 
fairly involved to rewrite it to do something else. There's also 
backward-compatibility to consider: third-party libraries can be 
inheriting from builtin types (e.g. numpy does this extensively) using 
the same copying-slot mechanism, which means those builtin types can't 
use the MRO walking to find their module without breaking compatibility 
with those third-party libraries.


The MRO walking code needs to deal with copied slots. It's not 
straigtforward, but I do think it's possible.



[...]

Static exceptions
-

A new function will be added::

     int PyErr_PrepareImmutableException(PyTypeObject **exc,
                                      const char *name,
                                      const char *doc,
                                      PyObject *base)

Creates an immutable exception type which can be shared
across multiple module objects.


How is this going to deal with type.__subclasses__()? Is re-using the 
static type object between reloads and sub-interpreters important enough 
to warrant the different behaviour? What if sub-interpreters end up 
wanting to disallow sharing objects between them?


Argh. Yes, subclasses seem to be the obvious shortcoming that a fresh 
pair of eyes is bound to find. Thanks!

This sends the proposal back to the drawing board.



[...]

Modules Converted in the Initial Implementation
---

To validate the approach, several modules will be modified during
the initial implementation:

The ``zipimport``, ``_io``, ``_elementtree``, and ``_csv`` modules
will be ported to PEP 489 multiphase initialization.


zipimport currently caches things in C globals. Changing it to use PEP 
489 multi-phase 

Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Terry Reedy

On 4/26/2018 6:20 AM, Steve Holden wrote:
On Thu, Apr 26, 2018 at 8:56 AM, Steven D'Aprano > wrote:


On Thu, Apr 26, 2018 at 03:31:13AM -0400, Terry Reedy wrote:
> On 4/25/2018 8:20 PM, Chris Angelico wrote:
> >On Thu, Apr 26, 2018 at 10:11 AM, Yury Selivanov
> >> wrote:
> >>Just yesterday this snippet was used on python-dev to show how great the
> >>new syntax is:
> >>
> >>           my_func(arg, buffer=(buf := [None]*get_size()), 
size=len(buf))
> 
> What strikes me as awful about this example is that len(buf) is 
> get_size(), so the wrong value is being named and saved. 
> 'size=len(buf)' is, in a sense, backwards.


Terry is absolutely right, and I'm to blame for that atrocity. Mea
culpa.

​Perhaps a better spelling would be

     my_func(arg, buffer=[None]*(buflen := get_size()), size=buflen)


That is exactly what I wrote in the continuation that Steven snipped.

--
Terry Jan Reedy


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Boundaries between numbers and identifiers

2018-04-26 Thread Serhiy Storchaka
In Python 2.5 `0or[]` was accepted by the Python parser. It became an 
error in 2.6 because "0o" became recognizing as an incomplete octal 
number. `1or[]` still is accepted.


On other hand, `1if 2else 3` is accepted despites the fact that "2e" can 
be recognized as an incomplete floating point number. In this case the 
tokenizer pushes "e" back and returns "2".


Shouldn't it do the same with "0o"? It is possible to make `0or[]` be 
parseable again. Python implementation is able to tokenize this example:


$ echo '0or[]' | ./python -m tokenize
1,0-1,1:NUMBER '0'
1,1-1,3:NAME   'or'
1,3-1,4:OP '['
1,4-1,5:OP ']'
1,5-1,6:NEWLINE'\n'
2,0-2,0:ENDMARKER  ''

On other hand, all these examples look weird. There is an assymmetry: 
`1or 2` is a valid syntax, but `1 or2` is not. It is hard to recognize 
visually the boundary between a number and the following identifier or 
keyword, especially if numbers can contain letters ("b", "e", "j", "o", 
"x") and underscores, and identifiers can contain digits. On both sides 
of the boundary can be letters, digits, and underscores.


I propose to change the Python syntax by adding a requirement that there 
should be a whitespace or delimiter between a numeric literal and the 
following keyword.


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] The new and improved PEP 572, same great taste with 75% less complexity!

2018-04-26 Thread Larry Hastings



On 04/26/2018 11:18 AM, Chris Angelico wrote:

In the reference implementation, it's just DUP_TOP followed by
STORE_FAST (well, technically by "whatever the assignment compiles
to", as it could be affected by global/nonlocal, closures, etc). Is
there much advantage to creating a new opcode?


Probably not much, but I thought we now lived in an age of wonders where 
common sequences of opcodes were getting mashed together into new 
more-complicated-but-redundant bytecodes (e.g. 
BUILD_MAP_UNPACK_WITH_CALL) just to save on dispatch overhead. You're 
right, it'd be a micro-optimization, and its value would be debatable.



//arry/
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Reserve ':=' for type-inferred variable initialization (was PEP 572)

2018-04-26 Thread Lukasz Langa

> On Apr 26, 2018, at 11:00 AM, Fatty Morgan  wrote:
> 
> I would like to urge you to reconsider the use of the token ':='
> for assignment expressions.
> 
> The natural interpretation of 'name := expr' is a PEP 526
> type-annotated variable initialization 'name : T = expr' with the
> type annotation T omitted, the tokens ':' and '=' coalesced, and
> the implied type T inferred as 'type(expr)'.

PEP 484 type checkers *always* infer the type of an assignment
based on the right-hand side's value.

The main reason we require PEP 526 annotations at all is when
your initial assignment is not useful for this inference.

The two most common examples of this are `None` and empty
containers.  In those cases the type checker is unable to infer
what the *intended* value should be, so it urges the programmer
to explicitly state it.

In this sense, `a := []` or `a := None` doesn't provide any
additional information.  And `a = 1` is already enough to determine
what the expected type is.


> The following should probably be discussed in python-ideas and
> would only be relevant for a more distant future, but while I
> have your attention, here are a couple of thoughts:

Discussing this here will add to noise for Chris and the BDFL.
Consider re-posting in python-ideas.

-- Ł
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] The new and improved PEP 572, same great taste with 75% less complexity!

2018-04-26 Thread Brett Cannon
With the new name restriction on the LHS, I'm now -0 on this. While I don't
think the benefits outweigh the overhead cost of pushing Python closer to
not fitting in my brain, I would admittedly use this if provided to me. (I
also put this in the bucket of consenting adult features; ripe for abuse,
but common sense should prevail much like with every other feature we have
added that could get over-used, e.g. decorators.)

On Tue, 24 Apr 2018 at 08:36 Chris Angelico  wrote:

> The most notable change since last posting is that the assignment
> target is no longer as flexible as with the statement form of
> assignment, but is restricted to a simple name.
>
> Note that the reference implementation has not been updated.
>
> ChrisA
>
>
> PEP: 572
> Title: Assignment Expressions
> Author: Chris Angelico 
> Status: Draft
> Type: Standards Track
> Content-Type: text/x-rst
> Created: 28-Feb-2018
> Python-Version: 3.8
> Post-History: 28-Feb-2018, 02-Mar-2018, 23-Mar-2018, 04-Apr-2018,
> 17-Apr-2018,
>   25-Apr-2018
>
>
> Abstract
> 
>
> This is a proposal for creating a way to assign to variables within an
> expression. Additionally, the precise scope of comprehensions is adjusted,
> to
> maintain consistency and follow expectations.
>
>
> Rationale
> =
>
> Naming the result of an expression is an important part of programming,
> allowing a descriptive name to be used in place of a longer expression,
> and permitting reuse.  Currently, this feature is available only in
> statement form, making it unavailable in list comprehensions and other
> expression contexts.  Merely introducing a way to assign as an expression
> would create bizarre edge cases around comprehensions, though, and to avoid
> the worst of the confusions, we change the definition of comprehensions,
> causing some edge cases to be interpreted differently, but maintaining the
> existing behaviour in the majority of situations.
>
>
> Syntax and semantics
> 
>
> In any context where arbitrary Python expressions can be used, a **named
> expression** can appear. This is of the form ``name := expr`` where
> ``expr`` is any valid Python expression, and ``name`` is an identifier.
>
> The value of such a named expression is the same as the incorporated
> expression, with the additional side-effect that the target is assigned
> that value::
>
> # Handle a matched regex
> if (match := pattern.search(data)) is not None:
> ...
>
> # A more explicit alternative to the 2-arg form of iter() invocation
> while (value := read_next_item()) is not None:
> ...
>
> # Share a subexpression between a comprehension filter clause and its
> output
> filtered_data = [y for x in data if (y := f(x)) is not None]
>
>
> Differences from regular assignment statements
> --
>
> Most importantly, since ``:=`` is an expression, it can be used in contexts
> where statements are illegal, including lambda functions and
> comprehensions.
>
> An assignment statement can assign to multiple targets, left-to-right::
>
> x = y = z = 0
>
> The equivalent assignment expression is parsed as separate binary
> operators,
> and is therefore processed right-to-left, as if it were spelled thus::
>
> assert 0 == (x := (y := (z := 0)))
>
> Statement assignment can include annotations. This would be syntactically
> noisy in expressions, and is of minor importance. An annotation can be
> given separately from the assignment if needed::
>
> x:str = "" # works
> (x:str := "") # SyntaxError
> x:str # possibly before a loop
> (x := "") # fine
>
> Augmented assignment is not supported in expression form::
>
> >>> x +:= 1
>   File "", line 1
> x +:= 1
> ^
> SyntaxError: invalid syntax
>
> Statement assignment is able to set attributes and subscripts, but
> expression assignment is restricted to names. (This restriction may be
> relaxed in a future version of Python.)
>
> Otherwise, the semantics of assignment are identical in statement and
> expression forms.
>
>
> Alterations to comprehensions
> -
>
> The current behaviour of list/set/dict comprehensions and generator
> expressions has some edge cases that would behave strangely if an
> assignment
> expression were to be used. Therefore the proposed semantics are changed,
> removing the current edge cases, and instead altering their behaviour
> *only*
> in a class scope.
>
> As of Python 3.7, the outermost iterable of any comprehension is evaluated
> in the surrounding context, and then passed as an argument to the implicit
> function that evaluates the comprehension.
>
> Under this proposal, the entire body of the comprehension is evaluated in
> its implicit function. Names not assigned to within the comprehension are
> located in the surrounding scopes, as with normal lookups. As one special
> case, a 

Re: [Python-Dev] The new and improved PEP 572, same great taste with 75% less complexity!

2018-04-26 Thread Chris Angelico
On Fri, Apr 27, 2018 at 4:07 AM, Larry Hastings  wrote:
> * I assume that--if we don't already have one--we'll add a new
> DUP_AND_STORE_FAST opcode for binding expressions.  On the other hand,
> "STORE_FAST n" followed by "LOAD_FAST n" is a common enough bytecode idiom
> that the peephole optimizer could notice it and pretty easily swap it for
> DUP_AND_STORE_FAST.

In the reference implementation, it's just DUP_TOP followed by
STORE_FAST (well, technically by "whatever the assignment compiles
to", as it could be affected by global/nonlocal, closures, etc). Is
there much advantage to creating a new opcode?

OTOH, I noticed a lot of STORE_FAST followed by LOAD_FAST in list
comprehensions. For instance, [x+1 for x in items] translates to:

  1   0 BUILD_LIST   0
  2 LOAD_FAST0 (.0)
>>4 FOR_ITER12 (to 18)
  6 STORE_FAST   1 (x)
  8 LOAD_FAST1 (x)
 10 LOAD_CONST   0 (1)
 12 BINARY_ADD
 14 LIST_APPEND  2
 16 JUMP_ABSOLUTE4
>>   18 RETURN_VALUE

In theory, STORE_FAST followed by LOAD_FAST could be transformed into
DUP_TOP followed by STORE_FAST, and then if there is any variable that
is stored fast and never loaded, it could be optimized out. That'd
leave this with just a DUP_TOP and no variable named 'x'. No idea
whether it'd be worth the effort though.

ChrisA
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Lukasz Langa
[Uncle T]
> So, to match your sarcasm, here's mine:  try using a feature for what
> it's good at instead of for what it's bad at ;-)

Yes, this is the fundamental wisdom.  Judging which is which is left as an
exercise to the programmer.

With this, I'm leaving the discussion.  With Guido and you on board for PEP
572, I feel that Chris' streak is indeed about to break.

Some parting hair-splitting follows.


> [Uncle T]
>>> One language feature conspicuous by absence in newbie
>>> confusions was, consistently, assignment expressions.  Read any book
>>> or tutorial for such a language, and you'll find very little space
>>> devoted to them too.
> 
> [Łukasz Langa ]
>> Well, you have an entire code style built around this feature called Yoda
>> conditions. You teach people on Day 1 to never ever confuse == with =. Some
>> compilers even warn about this because so many people did it wrong.
> 
[Uncle T]
> Sorry, I couldn't follow that.

You implied that newbies don't have to even know about assignments in
expressions.  I wanted to demonstrate that this isn't really the case because
mistaking `=` for `==` is a relatively common occurence for newbies.  If you
want to argue that it isn't, I'd like to point out that the WordPress code
style *requires* Yoda conditions because it was enough of a hindrance.  ESLint
(a JavaScript linter) also has a warning about assignment in a conditional.


[Uncle T]]
> In languages like C that use easily
> confused operator symbols, sure, people are forever typing "=" when
> they mean "==".  That's nothing to do with whether they _understand_
> what the different operators do, though.

What you're saying is true.  But for it to be true, newbies *have to* learn the
distinction, and the fact that yes, sometimes the programmer indeed meant to
put a single `=` sign in the conditional.  That's why we'll end up with the
Pascal assignment operator.  And that *is* a thing that you will have to
explain to newbies when they encounter it for the first time.  Sadly, googling
for a colon followed by an equal sign isn't trivial if you don't know what
you're looking for.


[Łukasz]
>> Well, you can also use it as a statement. But don't!
> 
[Uncle T]]
> Why not?  _Every_ expression in Python can be used as a statement.
> Nothing forbids it, and that's even (very!) useful at an interactive
> prompt.

Because it suggests different intent, because it's limited, because it's slower
at runtime, and because PEP 572 says so itself.


> At this point I think you must have a lower opinion of Python
> programmers than I have ;-)  If adding even a dozen characters to a
> line makes it exceed a reasonable line-length guide, the code was
> almost certainly too confusingly dense to begin with.

Around 5% of if and elif statements in the standard library don't fit a single
line *as is*.  Sure, that's a low percentage but that's over 1,000 statements.
If you're putting an `if` statement in a method, you are already starting out
with 71 characters left on the line.  Four of those are going to be taken by
"if", a space, and the colon.  Adding a parenthesized assignment expression
takes at least 10% of that available space.

The silver lining for me is that this makes the environment riper for
auto-formatting.


-- Ł
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Reserve ':=' for type-inferred variable initialization (was PEP 572)

2018-04-26 Thread Fatty Morgan
I would like to urge you to reconsider the use of the token ':='
for assignment expressions.

The natural interpretation of 'name := expr' is a PEP 526
type-annotated variable initialization 'name : T = expr' with the
type annotation T omitted, the tokens ':' and '=' coalesced, and
the implied type T inferred as 'type(expr)'.

There is an ongoing tendency to introduce possibilities for
static analysis into python, perhaps eventually resulting in a
statically typed variant of python were (optional) type
annotations are enforced (and used for optimizations), and it
would be a pity if this specific piece of obvious syntax had been
wasted on a comparatively unimportant feature.


The following should probably be discussed in python-ideas and
would only be relevant for a more distant future, but while I
have your attention, here are a couple of thoughts:

Distinguishing in a rather unobtrusive way (no 'var' or 'let')
the initialization of a previously unbound variable 'name := expr'
and the re-assignment of a previously bound variable 'name = expr'
would be beneficial in itself (this has been discussed before but
AFAIK not with this syntax). For example, 'global' and 'nonlocal'
would be redundant and could be deprecated.

The use of variable initializations with explicit type
annotations as in PEP 526 would only be required in situations
where the declared type is deliberately different from the
inferred type, e.g.
'any_var: object = 42; any_var = "foo"; #OK, no TypeError'.
In the majority of cases a simple 'name := expr' would be
sufficient and type-safe.

Destructuring initialization, e.g., 'a,b,c: int = range(3)' or
'a,b,c := range(3)', is possible (the annotated or inferred type
refers not to the type of the iterable but to the generated
type).  If it were forbidden (i.e., only a single name-variable
allowed) PEP 572 with ':=' could be simply implemented by parsing
'name := expr' as an expression rather than a statement (assuming
it is OK to introduce 'name' into the current scope) but
destructuring initialization appears to be the more important
feature and would make assignment expressions with ':='
ambiguous.

Implementation would be straightforward if 'name := expr' were
lowered to 'name: auto = expr' where the newly introduced abstract
type 'auto' simply acts as a token informing compile-time and/or
run-time what to do. An explicit type annotation with type
'auto' could be allowed and would help to teach the feature.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] The new and improved PEP 572, same great taste with 75% less complexity!

2018-04-26 Thread Larry Hastings



On 04/26/2018 06:27 AM, Kirill Balunov wrote:
Not sure, but if additional motivating examples are required, there is 
a common pattern for dynamic attribute lookup (snippet from `copy.py`):


    reductor = dispatch_table.get(cls)
    if reductor:
    rv = reductor(x)
    else:
    reductor = getattr(x, "__reduce_ex__", None)
    if reductor:
    rv = reductor(4)
    else:
    reductor = getattr(x, "__reduce__", None)
    if reductor:
    rv = reductor()
    else:
    raise Error("un(shallow)copyable object of type %s" % cls)

which can with the current `binding expression` syntax simplified to:

    if reductor := dispatch_table.get(cls):
    rv = reductor(x)
    elif reductor := getattr(x, "__reduce_ex__", None):
    rv = reductor(4)
    elif reductor := getattr(x, "__reduce__", None):
    rv = reductor()
    else:
    raise Error("un(shallow)copyable object of type %s" % cls)

which becomes much clearer, at least in my opinion.


I hate to be pedantic--there's enough of that going on in this 
thread--but I can't agree with the word "simplifed" above.  I agree that 
the code using binding expressions is /shorter./  But considering that 
emit the two code examples implement the exact same algorithm, to the 
point where their bytecode would look nearly* identical, ISTM that the 
two code examples are of identical /complexity./


Comparing the two, the code using the binding expressions obviates four 
newlines, three uses of the identifier "reductor", and allows folding 
two "else / if"s into "elif"s.  In exchange, it adds three extra colons, 
and the density of complexity per line has shot up. Whether or not 
that's an improvement is in the eye of the beholder, and I gather the 
battle lines around this PEP have already been clearly drawn.  But it 
cannot be said that this transformation has made the code simpler.


Personally, I've already voted -1; I don't see the version using the 
binding expressions as an improvement.  Expressing the same code using 
slightly fewer characters doesn't justify adding syntax to the language 
in my opinion.



//arry/

* I assume that--if we don't already have one--we'll add a new 
DUP_AND_STORE_FAST opcode for binding expressions.  On the other hand, 
"STORE_FAST n" followed by "LOAD_FAST n" is a common enough bytecode 
idiom that the peephole optimizer could notice it and pretty easily swap 
it for DUP_AND_STORE_FAST.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 572: Assignment Expressions

2018-04-26 Thread Chris Angelico
On Fri, Apr 27, 2018 at 3:33 AM, Sven R. Kunze  wrote:
> On 25.04.2018 01:19, Steven D'Aprano wrote:
>>
>> Sorry, gcd(diff, n) is not the "perfect name", and I will tell you that
>> sometimes g is better. [...]
>
>
> We were talking about the real-world code snippet of Tim (as a justification
> of := ) and alternative rewritings of it without resorting to new syntax.
> Not about "sometimes", or in some toy examples, or code without unknown
> life-time and intention (interactive, library, etc).

You're asking for some massive changes in semantics, though. If you
want to discuss that, it's nothing at all to do with PEP 572, and is a
completely new proposal.

>> You might know that, but how does somebody reading the code know
>> which functions are pure and which are not? How does the compiler know?
>
>
> There are invisible optimizations in CPython already.
> And for the most obvious examples, humans don't need to know. It's like
> wondering if constant folding really works.
> It's the same with all optimizations: if it works, it's fine. If it cannot
> be made working, the original code still works and you can optimize by hand
> anyway.
> The two obvious ways: the compiler might have a predefined list of pure
> functions OR the code tells him with an annotation of any sort.
> Both ways work, the latter somehow feels cleaner.

An annotation? You mean like functools.lru_cache? That's technically
nothing to do with pure functions, but it's about as much as you're
likely to get. The function still has to be called, and the result has
to be cached somewhere. Ultimately, "pure function optimization" is
just another form of cache.

Please, take this to python-ideas, or even better, to python-list.
It's not a counter-argument to PEP 572.

ChrisA
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 572: Write vs Read, Understand and Control Flow

2018-04-26 Thread Sven R. Kunze

On 24.04.2018 11:21, Victor Stinner wrote:

I have been asked to express myself on the PEP 572.


+1

I knew about the relationship between read and write. But your stance on 
debugging just makes it a thing. Thanks a lot!

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 572: Assignment Expressions

2018-04-26 Thread Sven R. Kunze

On 25.04.2018 01:19, Steven D'Aprano wrote:

Sorry, gcd(diff, n) is not the "perfect name", and I will tell you that
sometimes g is better. [...]


We were talking about the real-world code snippet of Tim (as a 
justification of := ) and alternative rewritings of it without resorting 
to new syntax.
Not about "sometimes", or in some toy examples, or code without unknown 
life-time and intention (interactive, library, etc).



You might know that, but how does somebody reading the code know
which functions are pure and which are not? How does the compiler know?


There are invisible optimizations in CPython already.
And for the most obvious examples, humans don't need to know. It's like 
wondering if constant folding really works.
It's the same with all optimizations: if it works, it's fine. If it 
cannot be made working, the original code still works and you can 
optimize by hand anyway.
The two obvious ways: the compiler might have a predefined list of pure 
functions OR the code tells him with an annotation of any sort.

Both ways work, the latter somehow feels cleaner.


It's easy to say that you recognise gcd as a pure function. How about
len(document.chapter[this_chapter].pages()), is that a pure function?


What exactly do you want me to answer? An algorithm? A trained neural 
network?
Usually, one starts with the low-hanging fruits and extends if possible 
and needed.

So that would be way out of scope.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (Looking for) A Retrospective on the Move to Python 3

2018-04-26 Thread Barry Warsaw
On Apr 26, 2018, at 09:28, Eric Snow  wrote:
> 
> On Thu, Apr 26, 2018 at 10:25 AM, Eric Snow  
> wrote:
>> In pondering our approach to future Python major releases, I found
>> myself considering the experience we've had with Python 3.  The whole
>> Py3k effort predates my involvement in the community so I missed a
>> bunch of context about the motivations, decisions, and challenges.
>> While I've pieced some of that together over the years now since I've
>> been around, I've certainly seen much of the aftermath.  For me, at
>> least, it would be helpful to have a bit more insight into the
>> history. :)

It would certainly be an interesting document, but I suspect you’ll get a bit 
of the old “ask 3 lawyers and get 5 opinions” kind of response. ;)

As I remember it, there was definitely a feeling like, this would be our only 
chance to clean up some annoying cruft, and rectify some (in hindsight) 
incorrect design decisions made over the years, couple with a healthy dose of 
“we have no idea how to do the bytes/str split in a backward compatible way".  
There was probably a sense that the Python community was just small enough to 
be able to handle such a disruptive change, but wouldn’t ever be so again.  The 
latter is definitely true today, even if the former was overly optimistic.

-Barry



signature.asc
Description: Message signed with OpenPGP
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] The new and improved PEP 572, same great taste with 75% less complexity!

2018-04-26 Thread Tim Peters
[Kirill Balunov ]
> Not sure, but if additional motivating examples are required, there is a
> common pattern for dynamic attribute lookup (snippet from `copy.py`):
>
> reductor = dispatch_table.get(cls)
> if reductor:
> rv = reductor(x)
> else:
> reductor = getattr(x, "__reduce_ex__", None)
> if reductor:
> rv = reductor(4)
> else:
> reductor = getattr(x, "__reduce__", None)
> if reductor:
> rv = reductor()
> else:
> raise Error("un(shallow)copyable object of type %s" % cls)
>
> which can with the current `binding expression` syntax simplified to:
>
> if reductor := dispatch_table.get(cls):
> rv = reductor(x)
> elif reductor := getattr(x, "__reduce_ex__", None):
> rv = reductor(4)
> elif reductor := getattr(x, "__reduce__", None):
> rv = reductor()
> else:
> raise Error("un(shallow)copyable object of type %s" % cls)
>
> which becomes much clearer, at least in my opinion.
>
> With kind regards,
> -gdg

Thanks for sharing that!  While nobody else seems to, I absolutely
love real code ;-)

This is effectively an instance of Guido's "if/elif/elif/elif/..."
example template, where binding expressions shine.  But actual real
code can make a point viscerally that "consider stuff akin to the
following semi-abstract pattern" can't.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] The new and improved PEP 572, same great taste with 75% less complexity!

2018-04-26 Thread Kirill Balunov
2018-04-24 18:31 GMT+03:00 Chris Angelico :

>
> Recommended use-cases
> =
>
> [...]
>
> # Capturing regular expression match objects
> # See, for instance, Lib/pydoc.py, which uses a multiline spelling
> # of this effect
> if match := re.search(pat, text):
> print("Found:", match.group(0))
>
>

Not sure, but if additional motivating examples are required, there is a
common pattern for dynamic attribute lookup (snippet from `copy.py`):

reductor = dispatch_table.get(cls)
if reductor:
rv = reductor(x)
else:
reductor = getattr(x, "__reduce_ex__", None)
if reductor:
rv = reductor(4)
else:
reductor = getattr(x, "__reduce__", None)
if reductor:
rv = reductor()
else:
raise Error("un(shallow)copyable object of type %s" % cls)

which can with the current `binding expression` syntax simplified to:

if reductor := dispatch_table.get(cls):
rv = reductor(x)
elif reductor := getattr(x, "__reduce_ex__", None):
rv = reductor(4)
elif reductor := getattr(x, "__reduce__", None):
rv = reductor()
else:
raise Error("un(shallow)copyable object of type %s" % cls)

which becomes much clearer, at least in my opinion.

With kind regards,
-gdg
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Every Release Can Be a Mini "Python 4000", Within Reason (was (name := expression) doesn't fit the narrative of PEP 20)

2018-04-26 Thread Eric Snow
On Thu, Apr 26, 2018 at 12:52 AM, Greg Ewing
 wrote:
> [snip]
> here we would be *creating* one (two different assignment
> operators with overlapping use cases) that we won't be
> able to get rid of without a Python 4000 (that Guido has
> promised won't happen).

The edict about "Python 4000" is more about not repeating what
happened with Python 3 than strictly prohibiting breaking backward
compatibility. [1]  The way I understand it, the problem with Py3k was
that so many things changed in a backward-incompatible way.  Folks
could have coped with the unicode change as the big one for Python 2.7
(or 2.8 or 3.0 or whatever it ended up being).  However, so many other
things changed all at once that the burden to move to Python 3 became
daunting.  This included a number of back-compat-breaking syntax
changes.

Unless I've missed something, there's no prohibition against
deprecating things (and then later removing them) or other breaks in
backward compatibility.  We certainly avoid it, with good reason.
However, when we do break compatibility, the thing we want to avoid is
introducing too many such changes all at once (and to keep in mind
that such changes can add up to the same detriment when viewed in
aggregate across multiple releases).

That said, syntax is definitely a trickier target when it comes to
breaking backward compatibility.  So we have to be especially careful
about adding it in the first place.  I suppose that's a big part of
the reason for the strong reaction to the "binding expressions"
proposal.

-eric


[1] I'm hopeful we can consolidate a retrospective on Python 3 in a
PEP:  https://mail.python.org/pipermail/python-dev/2018-April/153131.html
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] The new and improved PEP 572, same great taste with 75% less complexity!

2018-04-26 Thread Tim Peters
[Guido]
> Maybe the order for d[k] = v should also be reconsidered?

There's certainly code in the wild relying on the order "v, then d,
then k", because that's just how assignment statements have always
worked (dicts or not).  I'd rather change the dict comprehension code,
because I think the analogy to what `d[k] = v` does is weak.  I
expect:

{f(): g() for _ in [1]|

to do the same as

   {f(): g()}

The former currently evaluates g() first; the latter f().  Since I
also expect both of those to do the same as

dict((f(), g()) for _ in [1])

f() has to win ;-)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Is PEP 572 really the most effective way to solve the problems it's targeting?

2018-04-26 Thread Mike Miller

On 2018-04-25 19:36, Ryan Gonzalez wrote:

By now we've searched over the current proposal in excruciating detail.

However, there were two good questions in this message which I haven't seen 
addressed yet:


- How are other modern languages solving this issue?
- How does this new construct intersect with typing functionality?

-Mike
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (Looking for) A Retrospective on the Move to Python 3

2018-04-26 Thread Eric Snow
On Thu, Apr 26, 2018 at 10:25 AM, Eric Snow  wrote:
> In pondering our approach to future Python major releases, I found
> myself considering the experience we've had with Python 3.  The whole
> Py3k effort predates my involvement in the community so I missed a
> bunch of context about the motivations, decisions, and challenges.
> While I've pieced some of that together over the years now since I've
> been around, I've certainly seen much of the aftermath.  For me, at
> least, it would be helpful to have a bit more insight into the
> history. :)

As to motivation, I suppose (since I wasn't involved yet) that it was roughly:

let's bite the bullet and fix unicode with a backward-incompatible release

which led to:

well, we're already going to break backward compatibility so we might
as well get any breakage we're planning over with now so folks only
have to fix their code for this release

and then to:

oh, and while we're at it let's clean up a bunch of cruft that's built up
over the years

At least that's my impression. :)

-eric
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] (Looking for) A Retrospective on the Move to Python 3

2018-04-26 Thread Eric Snow
In pondering our approach to future Python major releases, I found
myself considering the experience we've had with Python 3.  The whole
Py3k effort predates my involvement in the community so I missed a
bunch of context about the motivations, decisions, and challenges.
While I've pieced some of that together over the years now since I've
been around, I've certainly seen much of the aftermath.  For me, at
least, it would be helpful to have a bit more insight into the
history. :)

With that in mind, it would be worth having an informational PEP with
an authoritative retrospective on the lessons learned from the Python
3 effort (and transition).  Consider it a sort of autobiography,
"memoirs on the python-dev change to Python 3". :)  At this point the
transition has settled in enough that we should be able to present a
relatively objective (and consistent) view, while we're not so far
removed that we've forgotten anything important. :)  If such a
document already exists then I'd love a pointer to it.

The document would benefit (among others):

* python-dev (by giving us a clear viewpoint to inform decisions about
future releases)
* new-comers to Python that want more insight into the language
* folks transitioning from 2 to 3
* communities that have (or think they have) problems similar to those
we faced in Python 2

The PEP doesn't even have to be done all at once, nor by one person.
In fact, there are many viewpoints that would add value to the
document.  Hence it would probably make sense to encourage broad
participation and then have a single editor to effect a single voice
in the document.

The contents of the retrospective document should probably cover a
broad range of topics, since there's so much to learn from the move to
Python 3.  To give an indication of what I mean, I've included a rough
outline at the bottom of this message.

So...I typically strongly avoid making proposals that I'm not willing
to execute.  However, in this case I simply do not have enough
experience in the history to feel comfortable doing a good job of it
in a reasonable amount of time (which matters due to the tendency of
valuable info to fade away). :/  I have no expectation that someone
will pick this up, though I do hope since the benefit would be
significant.  My apologies in advance if this wasted anyone's time.

-eric




I'd hope to see something along the lines of (at least) the following,
in rough order:

* a concise summary of the document at the top (very meta, I know :) )
  + what were we solving?
  + what was the solution?
  + why do it that way?
  + what went right?
  + what went wrong?
  + impact on the community
  + impact on core dev contribution
* timeline
* key players (and level of involvement)
  + old guard core devs
  + new guard
  + folks brought on for Py3k (e.g. IIRC a swarm of Googlers dove in)
  + non-core-devs
* motivations
* expectations (e.g. time frames, community reaction)
* corresponding results
* a summary of what we did
* alternative approaches
* what went right (and was it on purpose :) )
* what went wrong (e.g. io) and why
* how the Py3k project differed from normal python-dev workflow (e.g.
pace, decision-making, communications)
* lasting impact of python-dev
* key things that would have been better if done differently
* key decisions/planning (mostly a priori to the release work)
  + scope of backward compatibility
  + process (using PEPs with PEPs 30xx guiding)
  + schedule
  + specific changes (i.e. PEPs 31xx)
  + what was left out (and why)
  + plans to help library and app authors transition (e.g. 2to3)
  + feature/schedule overlap with Python 2 (i.e. 2.6 and 2.7)
  + the language moratorium
* things that got missed and why
  + unicode/bytes in some stdlib modules (and builtins?)
* things that were overdone (and how that got missed)
  + unicode/bytes in some stdlib modules (and builtins?)
* (last but not least) challenges faced by folks working to transition
their exiting code to Python 3
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] The new and improved PEP 572, same great taste with 75% less complexity!

2018-04-26 Thread Jim F.Hilliard
FWIW There's an existing issue (bpo 29652
) for the order of evaluation in
dict-comps.



Best Regards,

Jim Fasarakis Hilliard

On Thu, Apr 26, 2018 at 7:06 PM, Chris Angelico  wrote:

> On Fri, Apr 27, 2018 at 2:02 AM, Guido van Rossum 
> wrote:
> > Maybe the order for d[k] = v should also be reconsidered?
>
> If so, it would be something like:
>
> 1) Evaluate d
> 2) Evaluate k
> 3) Evaluate v
> 4) Call d.__setitem__(k, v), via slots etc
>
> In a vacuum, I don't have a problem with that. But I suspect that it'd
> break more code than the comprehensions changes do.
>
> ChrisA
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/d.
> f.hilliard%40gmail.com
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] The new and improved PEP 572, same great taste with 75% less complexity!

2018-04-26 Thread Chris Angelico
On Fri, Apr 27, 2018 at 2:02 AM, Guido van Rossum  wrote:
> Maybe the order for d[k] = v should also be reconsidered?

If so, it would be something like:

1) Evaluate d
2) Evaluate k
3) Evaluate v
4) Call d.__setitem__(k, v), via slots etc

In a vacuum, I don't have a problem with that. But I suspect that it'd
break more code than the comprehensions changes do.

ChrisA
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] The new and improved PEP 572, same great taste with 75% less complexity!

2018-04-26 Thread Guido van Rossum
Maybe the order for d[k] = v should also be reconsidered?

On Thu, Apr 26, 2018, 08:23 Chris Angelico  wrote:

> On Fri, Apr 27, 2018 at 1:07 AM, Guido van Rossum 
> wrote:
> > Just as I feared. While currently fixing this is just fixing a bug
> (nobody's
> > code is going to break except perhaps some tests), with PEP 572 fixing
> this
> > would be mandatory.
> >
> > On Thu, Apr 26, 2018 at 6:57 AM, Nick Coghlan 
> wrote:
> >>
> >> On 25 April 2018 at 18:23, Chris Angelico  wrote:
> >>  x={print(2): print(1) for _ in [1]}
> >> > 1
> >> > 2
> >> >
> >> > Hm. One of these is not like the others...
> >>
> >> Huh, it looks like we missed checking dict comprehensions when we
> >> fixed dict displays to evaluate keys before the corresponding values.
> >> That would qualify as a reasonable request for improvement in Python
> >> 3.8 :)
>
> It's deliberate code in compile.c:
>
> case COMP_DICTCOMP:
> /* With 'd[k] = v', v is evaluated before k, so we do
>the same. */
> VISIT(c, expr, val);
> VISIT(c, expr, elt);
> ADDOP_I(c, MAP_ADD, gen_index + 1);
> break;
>
> So if it's a bug, it's still a deliberate bug. :)
>
> ChrisA
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/guido%40python.org
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Łukasz Langa

> On Apr 25, 2018, at 11:10 PM, Steven D'Aprano  wrote:
> Criticising binding- 
> expressions for that reason, especially implying that we must always use 
> parens, is simply FUD.

The PEP has more examples with parentheses than without.

>> As soon as we have to wrap a part of an expression in parentheses, 
>> parsing the entire thing becomes more complex.
> 
> Unless it becomes less complex to read and understand.

You're ignoring the context of the discussion. The new parentheses are there 
because there's a new assignment there. That's more complex.


>> Often enough it will 
>> cause the expression to exceed whatever line length limit the codebase 
>> pledged not to exceed, causing one line to become three.
> 
> Just how often are your lines within two characters of the maximum 
> column so that adding a pair of brackets () will "often enough" put it 
> over the limit? Seems pretty unlikely to me.

Again, you're ignoring the context of the discussion. Assuming := will have 
spaces around it in PEP 8, this is adding *at least* 7 characters if the name 
of your choice is a single character.


> This sounds really like 
> picking at straws.

The entire point of the PEP is to make things "nicer". It doesn't fundamentally 
enable programmers to do anything they couldn't do before.

If you think demonstrating cases where the end result won't be an improvement 
is picking at straws, then maybe the improvement of PEP 572 is as well.

-- Ł

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 572: Why not := as standard assignment operator?

2018-04-26 Thread Chris Angelico
On Fri, Apr 27, 2018 at 1:38 AM, Gustavo Carneiro  wrote:
>
>
> On 26 April 2018 at 16:18, Chris Angelico  wrote:
>>
>> On Thu, Apr 26, 2018 at 11:13 PM, Martin Teichmann
>>  wrote:
>> > Hi list,
>> >
>> > when reading PEP 572 I actually liked it a lot - I think it's actually
>> > a cool idea. I think it's actually that cool an idea that it should be
>> > made the default way of doing an assignment, over time phasing out the
>> > good ole =.
>> >
>> > This would have several benefits:
>> >
>> > - people wouldn't have to worry about two different options
>> > - different things would have a different look: assignment is :=,
>> > keyword args is =, while comparison is ==. Especially beginners would
>> > benefit from this clarity.
>> >
>> > in this case, for sure, we should make it possible to chain :=s, for
>> > example by making it bind right-to-left, so that  a := b := 3 would be
>> > a := (b := 3)
>> >
>> > I'm sorry if somebody brought that up already, but the discussion has
>> > grown so huge that I couldn't read through it entirely.
>>
>> It has indeed grown huge. And in the interests of not growing it even
>> huger, I'm not going to rehash the arguments against making := into
>> the one and only operator, save to say one thing: there's no way that
>> "x = 1" can be removed from the language any time soon, and by "soon"
>> I mean even by the Yes Prime Minister definition, where "any day now",
>> in strategic terms, meant "within the next half century".
>
>
> In the interest of that, do you think := can be made illegal, by the
> grammar, if used outside an expression?
>
> a = 1  # legal
> a := 1  # Syntax error
> if a := 1:  # legal
>

No. Any expression may be used as a statement, so this isn't "outside
an expression".

ChrisA
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 572: Why not := as standard assignment operator?

2018-04-26 Thread Gustavo Carneiro
On 26 April 2018 at 16:18, Chris Angelico  wrote:

> On Thu, Apr 26, 2018 at 11:13 PM, Martin Teichmann
>  wrote:
> > Hi list,
> >
> > when reading PEP 572 I actually liked it a lot - I think it's actually
> > a cool idea. I think it's actually that cool an idea that it should be
> > made the default way of doing an assignment, over time phasing out the
> > good ole =.
> >
> > This would have several benefits:
> >
> > - people wouldn't have to worry about two different options
> > - different things would have a different look: assignment is :=,
> > keyword args is =, while comparison is ==. Especially beginners would
> > benefit from this clarity.
> >
> > in this case, for sure, we should make it possible to chain :=s, for
> > example by making it bind right-to-left, so that  a := b := 3 would be
> > a := (b := 3)
> >
> > I'm sorry if somebody brought that up already, but the discussion has
> > grown so huge that I couldn't read through it entirely.
>
> It has indeed grown huge. And in the interests of not growing it even
> huger, I'm not going to rehash the arguments against making := into
> the one and only operator, save to say one thing: there's no way that
> "x = 1" can be removed from the language any time soon, and by "soon"
> I mean even by the Yes Prime Minister definition, where "any day now",
> in strategic terms, meant "within the next half century".
>

In the interest of that, do you think := can be made illegal, by the
grammar, if used outside an expression?

a = 1  # legal
a := 1  # Syntax error
if a := 1:  # legal

Thanks in advance.

-- 
Gustavo J. A. M. Carneiro
Gambit Research
"The universe is always one step beyond logic." -- Frank Herbert
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] The new and improved PEP 572, same great taste with 75% less complexity!

2018-04-26 Thread Chris Angelico
On Fri, Apr 27, 2018 at 1:07 AM, Guido van Rossum  wrote:
> Just as I feared. While currently fixing this is just fixing a bug (nobody's
> code is going to break except perhaps some tests), with PEP 572 fixing this
> would be mandatory.
>
> On Thu, Apr 26, 2018 at 6:57 AM, Nick Coghlan  wrote:
>>
>> On 25 April 2018 at 18:23, Chris Angelico  wrote:
>>  x={print(2): print(1) for _ in [1]}
>> > 1
>> > 2
>> >
>> > Hm. One of these is not like the others...
>>
>> Huh, it looks like we missed checking dict comprehensions when we
>> fixed dict displays to evaluate keys before the corresponding values.
>> That would qualify as a reasonable request for improvement in Python
>> 3.8 :)

It's deliberate code in compile.c:

case COMP_DICTCOMP:
/* With 'd[k] = v', v is evaluated before k, so we do
   the same. */
VISIT(c, expr, val);
VISIT(c, expr, elt);
ADDOP_I(c, MAP_ADD, gen_index + 1);
break;

So if it's a bug, it's still a deliberate bug. :)

ChrisA
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 572: Why not := as standard assignment operator?

2018-04-26 Thread Chris Angelico
On Thu, Apr 26, 2018 at 11:13 PM, Martin Teichmann
 wrote:
> Hi list,
>
> when reading PEP 572 I actually liked it a lot - I think it's actually
> a cool idea. I think it's actually that cool an idea that it should be
> made the default way of doing an assignment, over time phasing out the
> good ole =.
>
> This would have several benefits:
>
> - people wouldn't have to worry about two different options
> - different things would have a different look: assignment is :=,
> keyword args is =, while comparison is ==. Especially beginners would
> benefit from this clarity.
>
> in this case, for sure, we should make it possible to chain :=s, for
> example by making it bind right-to-left, so that  a := b := 3 would be
> a := (b := 3)
>
> I'm sorry if somebody brought that up already, but the discussion has
> grown so huge that I couldn't read through it entirely.

It has indeed grown huge. And in the interests of not growing it even
huger, I'm not going to rehash the arguments against making := into
the one and only operator, save to say one thing: there's no way that
"x = 1" can be removed from the language any time soon, and by "soon"
I mean even by the Yes Prime Minister definition, where "any day now",
in strategic terms, meant "within the next half century".

For further details, search the archives. Please don't reply to debate
this point. :)

ChrisA
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] The new and improved PEP 572, same great taste with 75% less complexity!

2018-04-26 Thread Guido van Rossum
Just as I feared. While currently fixing this is just fixing a bug
(nobody's code is going to break except perhaps some tests), with PEP 572
fixing this would be mandatory.

On Thu, Apr 26, 2018 at 6:57 AM, Nick Coghlan  wrote:

> On 25 April 2018 at 18:23, Chris Angelico  wrote:
>  x={print(2): print(1) for _ in [1]}
> > 1
> > 2
> >
> > Hm. One of these is not like the others...
>
> Huh, it looks like we missed checking dict comprehensions when we
> fixed dict displays to evaluate keys before the corresponding values.
> That would qualify as a reasonable request for improvement in Python
> 3.8 :)
>
> Cheers,
> Nick.
>
> --
> Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/
> guido%40python.org
>



-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 573 -- Module State Access from C Extension Methods

2018-04-26 Thread Jeroen Demeyer

On 2018-04-26 16:37, Nick Coghlan wrote:

PEP 487 refers to this as the "owner" of a descriptor


That's just copied from the Python docs:

https://docs.python.org/3.8/reference/datamodel.html#object.__get__

Anyway, I never liked the name "owner" there, "cls" would have been much 
clearer.


For PEP 575, I thought of "owner" too, but I don't like it because it 
sounds too possessive. It sounds like the "owner" somehow has complete 
control over the function and I don't want that association.

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 573 -- Module State Access from C Extension Methods

2018-04-26 Thread Nick Coghlan
On 26 April 2018 at 04:46, Jeroen Demeyer  wrote:
> On 2018-04-25 20:33, Petr Viktorin wrote:
>>
>> Perhaps "m_objclass" could point to the module in this case
>
>
> That was exactly my idea also today. Instead of treating m_objclass as the
> defining class, we should generalize it to be the "parent" of the function:
> either the class or the module.

PEP 487 refers to this as the "owner" of a descriptor (See the
"__set_name__" example implementation in
https://www.python.org/dev/peps/pep-0487/#trait-descriptors ).

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Nick Coghlan
On 26 April 2018 at 15:38, Chris Angelico  wrote:
> On Thu, Apr 26, 2018 at 3:34 PM, Steven D'Aprano  wrote:
>> Can you give an example of a Python expression, involving PEP 572
>> binding-expressions, that is not a tree but a more general DAG or that
>> contains cycles?
>
> A DAG is a directed *acyclic* graph, so it still can't contain cycles.
> But I have no idea what kind of expression isn't a tree as a
> consequence of having an assignment in it.

At a parsing level, the expression remains a tree, it's just that one
of the nodes is a name lookup. At a logical level though, binding
expressions do indeed mean that expressions involving binding
expressions are at least arguably better modelled with a DAG rather
than as a tree the way they are now:

# The arithmetic expression is a tree including two nodes that
look up "c". The DAG is only needed at a statement level.
c = expr()
a*c + b*c

# Whereas this backref to "c" pulls the DAG down to the expression level
a*(c := expr()) + b*c

Historically, that kind of order-of-evaluation dependence in Python
has only been a problem for functions with side effects, so the folks
asking that this be seen as a major complexity increase for expression
level semantics have an entirely valid point. The PEP aims to address
that point by saying "Don't use binding expressions when the order of
evaluation would be ambiguous", but that's as a response to a valid
concern, not a dismissal of it.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] The new and improved PEP 572, same great taste with 75% less complexity!

2018-04-26 Thread Nick Coghlan
On 25 April 2018 at 18:23, Chris Angelico  wrote:
 x={print(2): print(1) for _ in [1]}
> 1
> 2
>
> Hm. One of these is not like the others...

Huh, it looks like we missed checking dict comprehensions when we
fixed dict displays to evaluate keys before the corresponding values.
That would qualify as a reasonable request for improvement in Python
3.8 :)

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 573 -- Module State Access from C Extension Methods

2018-04-26 Thread Thomas Wouters
Thanks for working on this, Marcel (and Petr). This looks like an ambitious
intern project :) Couple of questions and comments in-line.

On Mon, Apr 23, 2018 at 12:36 PM, Marcel Plch 
wrote:

> Hello,
> I am an intern at Red Hat mentored by Petr Viktorin. As a part of my
> internship, I learned the CPython internals and how to contribute
> to the CPython interpreter.
>
> As a result, I have prepared PEP 573, which solves some problems
> that PEP 489 (Multi-phase extension module initialization) has left open.
> Specifically, this PEP proposes a way to access per-module state from
> methods of
> built-in and extension types.
> Like PEP 489, it aims to make subinterpreter-friendly built-in/extension
> modules
> easier to create.
>
> A big problem found when converting many modules to PEP 489 multi-phase
> initialization is subinterpreter-friendly access to exception
> types defined in built-in/extension modules.
> This PEP solves this by introducing "immutable exception types".
> The current implementation requires one new type flag and two new
> pointers in the heap type structure.
> It should be possible to remove eiher the flag or one of the two pointers,
> if we agree on the other mechanics in the PEP .
>
>
> ===
>
> PEP: 573
> Title: Module State Access from C Extension Methods
> Version: $Revision$
> Last-Modified: $Date$
> Author: Petr Viktorin ,
> Nick Coghlan ,
> Eric Snow ,
> Marcel Plch 
> Discussions-To: import-...@python.org
> Status: Active
> Type: Process
> Content-Type: text/x-rst
> Created: 02-Jun-2016
> Python-Version: 3.8
> Post-History:
>
>
> Abstract
> 
>
> This PEP proposes to add a way for CPython extension methods to access
> context such as
> the state of the modules they are defined in.
>
> This will allow extension methods to use direct pointer dereferences
> rather than PyState_FindModule for looking up module state, reducing
> or eliminating the
> performance cost of using module-scoped state over process global state.
>
> This fixes one of the remaining roadblocks for adoption of PEP 3121
> (Extension
> module initialization and finalization) and PEP 489
> (Multi-phase extension module initialization).
>
> Additionaly, support for easier creation of immutable exception
> classes is added.
>

I'm not a fan of using 'immutable' here, or in the API function name. I
understand the types are to some extent immutable (apart from their
refcount, I assume), but I think it's going to be too easy to confuse it
with types whose *instances* are immutable. (We do occasionally say things
like "tuples are an immutable type".) Since the point is that they behave
like statically defined ones, perhaps 'Static' would be a reasonable
replacement.

This removes the need for keeping per-module state if it would only be used
> for exception classes.
>
> While this PEP takes an additional step towards fully solving the
> problems that PEP 3121 and PEP 489 started
> tackling, it does not attempt to resolve *all* remaining concerns. In
> particular, accessing the module state from slot methods (``nb_add``,
> etc) remains slower than accessing that state from other extension
> methods.
>
>
> Terminology
> ===
>
> Process-Global State
> 
>
> C-level static variables. Since this is very low-level
> memory storage, it must be managed carefully.
>
> Per-module State
> 
>
> State local to a module object, allocated dynamically as part of a
> module object's initialization. This isolates the state from other
> instances of the module (including those in other subinterpreters).
>
> Accessed by ``PyModule_GetState()``.
>
>
> Static Type
> ---
>
> A type object defined as a C-level static variable, i.e. a compiled-in
> type object.
>
> A static type needs to be shared between module instances and has no
> information of what module it belongs to.
> Static types do not have ``__dict__`` (although their instances might).
>
> Heap Type
> -
>
> A type object created at run time.
>
>
> Rationale
> =
>
> PEP 489 introduced a new way to initialize extension modules, which brings
> several advantages to extensions that implement it:
>
> * The extension modules behave more like their Python counterparts.
> * The extension modules can easily support loading into pre-existing
>   module objects, which paves the way for extension module support for
>   ``runpy`` or for systems that enable extension module reloading.
> * Loading multiple modules from the same extension is possible, which
>   makes testing module isolation (a key feature for proper
> sub-interpreter
>   support) possible from a single interpreter.
>
> The biggest hurdle for adoption of PEP 489 is allowing access to module
> state
> from methods of extension types.
> Currently, the way to access this state 

[Python-Dev] PEP 572: Why not := as standard assignment operator?

2018-04-26 Thread Martin Teichmann
Hi list,

when reading PEP 572 I actually liked it a lot - I think it's actually
a cool idea. I think it's actually that cool an idea that it should be
made the default way of doing an assignment, over time phasing out the
good ole =.

This would have several benefits:

- people wouldn't have to worry about two different options
- different things would have a different look: assignment is :=,
keyword args is =, while comparison is ==. Especially beginners would
benefit from this clarity.

in this case, for sure, we should make it possible to chain :=s, for
example by making it bind right-to-left, so that  a := b := 3 would be
a := (b := 3)

I'm sorry if somebody brought that up already, but the discussion has
grown so huge that I couldn't read through it entirely.

Greetings

Martin
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread David Mertz
FWIW, the combination of limiting the PEP to binding expressions and the
motivating example of sequential if/elif tests that each need to utilize an
expression in their body (e.g. matching various regexen by narrowing,
avoiding repeated indent) gets me to +1.

I still think the edge case changes to comprehension semantics is needless
for this PEP. However, it concerns a situation I don't think I've ever
encountered in the wild, and certainly never relied on the old admittedly
odd behavior.

On Thu, Apr 26, 2018, 2:01 AM Tim Peters  wrote:

> Yes, binding expressions in the current PEP support an extremely
> limited subset of what Python's assignment statements support.[...]
> Guido's if/elif/elif/elif/ ... complex text-processing example didn't,
> but because the current lack of an ability to bind-and-test in one
> gulp forced the `elif` parts to be ever-more-deeply-indented `if`
> blocks instead.
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 572: Write vs Read, Understand and Control Flow

2018-04-26 Thread Chris Angelico
On Thu, Apr 26, 2018 at 9:23 PM, Stephen J. Turnbull
 wrote:
> Chris Angelico writes:
>
>  > Well, true. The point isn't WHO you're dictating to,
>
> By "period here preferred," I meant I think it's mostly a waste of
> space to mention dictation at all in that document.  But it's not a
> big deal to me, so how about changing "a student or junior programmer"
> to "another programmer"?
>
>

Sure, that works.

ChrisA
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Steven D'Aprano
On Thu, Apr 26, 2018 at 10:34:29PM +1200, Greg Ewing wrote:
> Antoine Pitrou wrote:
> >Well, how do languages where assignment is an expression returning the
> >assigned value make their REPLs work?  I'm sure they don't inflict that
> >on their users, so it's certainly a solvable problem.
> 
> I can't think of any such language that has a REPL
> offhand, but here's a possible solution:


Here's the Rhino Javascript REPL:

[steve@ando ~]$ rhino
Rhino 1.7 release 0.7.r2.3.el5_6 2011 05 04
js> x = (a = 99) + 1
100


Here's the standard Ruby REPL:

[steve@ando ~]$ irb
irb(main):001:0> x = (a = 99) + 1
=> 100


So both of these REPLs do print the result of the expression.

R, on the other hand, doesn't print the results of assignment 
expressions:

> x <- (a <- 99) + 1
> c(x, a)
[1] 100  99

Rhino, however, does suppress printing if you prefix the variable with 
"var" or "const".



-- 
Steve
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Steven D'Aprano
On Thu, Apr 26, 2018 at 10:17:34AM +0200, Antoine Pitrou wrote:

> I also wonder how long it will be before someone writes:
> 
> def f(arg):
> global _lazy_value
> if predicate(arg) and (_lazy_value := frobnicate()) > arg:
> ...
> 
> (or something similar with "nonlocal")

What if they did? I don't think that's especially worse than any other 
use of a global, including the current version:

def f(arg):
global _lazy_value
_lazy_value = frobnicate()
if predicate(arg) and _lazy_value > arg:
...


I'm not putting either version forward as paragons of Pythonic code, but 
honestly, they're not so awful that we should reject this PEP because of 
the risk that somebody will do this. People write crappy code and misuse 
features all the time. I cannot count the number of times people write 
list comps just for the side-effects, intentionally throwing away the 
resulting list:

[alist.sort() for alist in list_of_lists]
[print(alist) for alist in list_of_lists]

and the honest truth is that when I'm engaged in exploratory coding in 
the REPR, sometimes if I'm feeling lazy I'll do it too. The world goes 
on, and comprehensions are still useful even if people sometimes misuse 
them.



-- 
Steve
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread David Mertz
>
> [Raymond Hettinger ]
> > Python is special, in part, because it is not one of those languages.
> > It has virtues that make it suitable even for elementary school children.
> > We can show well-written Python code to non-computer folks and walk
> > them through what it does without their brains melting (something I can't
> > do with many of the other languages I've used).  There is a virtue
> > in encouraging simple statements that read like English sentences
> > organized into English-like paragraphs, presenting itself like
> > "executable pseudocode".


While this is true and good for most Python code, can you honestly explain
asyncio code with async/await to these non-programmers?! What about the
interfaces between async and synchronous portions?

I've been programming for 40 years, in Python for 20 of them. I cannot read
any block of async code without thinking VERY SLOWLY about what's going on,
then getting it wrong half the time. I even teach Python almost as much as
Raymond does.

There's a certain hand-waving approach to teaching async/await where you
say not to worry about those keywords, and just assume the blocks are
coordinated "somehow, behind the scenes." That's not awful for reading
*working* code, but doesn't let you write it.

I'm not saying binding expressions are likewise reserved for a special but
important style of programming. If included, I expect them to occur
more-or-less anywhere. So Raymond's concern about teachability is more
pressing (I've only taught async twice, and I know Raymond's standard
course doesn't do it, all the other code is unaffected by that unused
'await' lurking in the syntax). Still, there are good reasons why not all
Python code is aimed at non-computer folks.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Is PEP 572 really the most effective way to solve the problems it's targeting?

2018-04-26 Thread Antoine Pitrou
On Thu, 26 Apr 2018 20:35:20 +0900
"Stephen J. Turnbull"  wrote:

> Steven D'Aprano writes:
>  > On Wed, Apr 25, 2018 at 09:36:31PM -0500, Ryan Gonzalez wrote:  
> 
>  > > Now, what's the common theme here? **Declarations should be separate 
> from 
>  > > expressions.**  
>  > 
>  > Declarations and assignments are not the same thing.  
> 
> Ryan mostly meant "initialization" rather than "declaration", I
> suspect.  In C's for() statement, the first clause in parentheses is
> initialization, the third is assignment.
> 
> FWIW, I had been thinking the same thing (that what is really wanted
> is initialization clauses in loop statements) but had no concrete
> suggestions.  Now I too have warmed to the binding expression approach
> (partly because Guido has, so I'm preparing for the inevitable :^),
> mostly because of Tim's "humorous observation" about use in printf
> debugging.  The fact that there is this use case independent of block
> variable initialization (ie, in a loop or if statement) is quite
> attractive to me.
> 
> It's true, as I think Antoine pointed out, that it's easy enough to
> define a wrapper function that prints a value and returns it.

That wasn't me, but I agree with the idea anyway :-)

Regards

Antoine.


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Is PEP 572 really the most effective way to solve the problems it's targeting?

2018-04-26 Thread Stephen J. Turnbull
Steven D'Aprano writes:
 > On Wed, Apr 25, 2018 at 09:36:31PM -0500, Ryan Gonzalez wrote:

 > > Now, what's the common theme here? **Declarations should be separate from 
 > > expressions.**
 > 
 > Declarations and assignments are not the same thing.

Ryan mostly meant "initialization" rather than "declaration", I
suspect.  In C's for() statement, the first clause in parentheses is
initialization, the third is assignment.

FWIW, I had been thinking the same thing (that what is really wanted
is initialization clauses in loop statements) but had no concrete
suggestions.  Now I too have warmed to the binding expression approach
(partly because Guido has, so I'm preparing for the inevitable :^),
mostly because of Tim's "humorous observation" about use in printf
debugging.  The fact that there is this use case independent of block
variable initialization (ie, in a loop or if statement) is quite
attractive to me.

It's true, as I think Antoine pointed out, that it's easy enough to
define a wrapper function that prints a value and returns it.  But
that's not as flexible, and if you have more than one variable to
"watch", you either need an argument to the wrapper to provide the
variable's name, or different functions for different variables.

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Stephen J. Turnbull
Łukasz Langa writes:
 > > On 25 Apr, 2018, at 5:20 PM, Chris Angelico  wrote:

 > You're claiming that `:=` is nicer in this situation because it's less
 > prominent than regular assignment and thus doesn't suggest that the name
 > stays visible later.

FWIW, I read what he wrote as "*assuming* buf is not going to be used
later", and thus took a more nuanced idea from it: Use a separate
statement when you do use it later, and use a binding expression when
its scope is *in fact* only that line.

BTW, I don't find the "it could be misused, so it will be misused"
argument persuasive.  I agree it's true, but don't think it matters,
per the "consenting adults" principle, since binding expressions have
other, important, use cases.

We could add a statement to PEP 8 mildly deprecating this particular
use.  How about this:

In some examples, the binding expression is used in function
arguments where one argument depends on an earlier one, such as

foo(buffer=(buf := [None]*get_size()), size=len(buf))

In examples like this one, it is preferable where possible to
refactor the function to calculate the dependent variable itself,
or to use an assignment statement to define the bound variable.
The latter style is *strongly* preferred when the bound variable
will be used later in the scope.

Steve

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 572: Write vs Read, Understand and Control Flow

2018-04-26 Thread Stephen J. Turnbull
Chris Angelico writes:

 > Well, true. The point isn't WHO you're dictating to,

By "period here preferred," I meant I think it's mostly a waste of
space to mention dictation at all in that document.  But it's not a
big deal to me, so how about changing "a student or junior programmer"
to "another programmer"?


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Greg Ewing

Antoine Pitrou wrote:

Depends if you mean a graph between names or values?

>

If between names, you can even have cycles AFAICT:

  ((a: = a + b), (b: = a))


I was thinking more of the dataflow graph. That's not
a cycle between *values*, since the new values being
bound are calculated from the previous values of the
names.

--
Greg

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Greg Ewing

Antoine Pitrou wrote:

Well, how do languages where assignment is an expression returning the
assigned value make their REPLs work?  I'm sure they don't inflict that
on their users, so it's certainly a solvable problem.


I can't think of any such language that has a REPL
offhand, but here's a possible solution:


   x := expr # doesn't print anything

   (x := expr) # prints the result

I.e. special-case a stand-alone assignment, but
allow overriding that with parens if needed.

--
Greg

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Steve Holden
On Thu, Apr 26, 2018 at 8:56 AM, Steven D'Aprano 
wrote:

> On Thu, Apr 26, 2018 at 03:31:13AM -0400, Terry Reedy wrote:
> > On 4/25/2018 8:20 PM, Chris Angelico wrote:
> > >On Thu, Apr 26, 2018 at 10:11 AM, Yury Selivanov
> > > wrote:
> > >>Just yesterday this snippet was used on python-dev to show how great
> the
> > >>new syntax is:
> > >>
> > >>   my_func(arg, buffer=(buf := [None]*get_size()),
> size=len(buf))
> >
> > What strikes me as awful about this example is that len(buf) is
> > get_size(), so the wrong value is being named and saved.
> > 'size=len(buf)' is, in a sense, backwards.
>
> Terry is absolutely right, and I'm to blame for that atrocity. Mea
> culpa.
>
> ​Perhaps a better spelling would be

my_func(arg, buffer=[None]*(buflen := get_size()), size=buflen)

​[...]
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Steve Holden
On Wed, Apr 25, 2018 at 9:55 PM, Łukasz Langa  wrote:

>
> > On 25 Apr, 2018, at 1:28 PM, Guido van Rossum  wrote:
> >
> > You don't seem to grasp the usability improvements this will give. I
> hear you but at this point appeals to Python's "Zen" don't help you.
>
> This reads dismissive to me. I did read the PEP and followed the
> discussion on
> python-dev. I referred to PEP 20 because it distills what's unique about
> the
> value proposition of Python. It's our shared vocabulary.
>
> ​Perhaps so, but no PEP is chiselled in stone, and I would suggest that
PEP 20 is the least authoritative from a didactic point of view.
​


> Can you address the specific criticism I had? To paraphrase it without PEP
> 20
> jargon:
>
> > (name := expression) makes code less uniform.  It inserts more
> information
> > into a place that is already heavily packed with information (logic
> tests).
>
>
​One could argue the same about list comprehensions if one chose: they make
code denser (by expressing the same algorithm in a shorter spelling). I'm
not sure what you mean by "less uniform."​
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Antoine Pitrou
On Thu, 26 Apr 2018 19:19:05 +1000
Chris Angelico  wrote:
> >
> > If such were the need, you could very well make it part of the language
> > specification.  We are talking about a trivial optimization that any
> > runtime could easily implement (e.g. if a sequence `DUP_TOP, STORE_FAST,
> > POP_TOP` occurs, replace it with `STORE_FAST`).  
> 
> Not at the REPL, no. At the REPL, you need to actually print out that
> value. It's semantically different.

The REPL compiles expressions in a different mode than regular modules,
so that's entirely a strawman.  The REPL doesn't care that it will
spend a fraction of microseconds executing two additional bytecodes
before presenting something to the user.

> > Any runtime already has to implement a set of performance properties
> > that's far less trivial than that.  For example, any decent runtime is
> > expected to provide amortized O(1) list append or dict insertion.  You
> > are breaking user expectations if you don't.  
> 
> You assume that, but it isn't always the case.

Yeah, so what?

> Did you know, for instance, that string subscripting (an O(1) operation in 
> CPython) is
> allowed to be O(n) in other Python implementations?

Why would I give a sh*t?  Here, we are not talking about a non-trivial
design decision such as how to represent string values internally
(utf-8 vs. fixed-width, etc.).  We are talking about optimizing a
trivial bytecode sequence into another more trivial bytecode sequence.
CPython can easily do it.  PyPy can easily do it.  Other runtimes can
easily do it.

If some implementation is significantly slower because it can't
optimize away pointless DUP_TOPs *and* it implements DUP_TOP
inefficiently enough to have user-noticeable effect, then it's either
1) a deliberate toy, a proof-of-concept not meant for serious use, or
2) a pile of crap produced by incompetent people.

So there's zero reason to bother about efficiency issues here.

Regards

Antoine.


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Chris Angelico
On Thu, Apr 26, 2018 at 6:30 PM, Antoine Pitrou  wrote:
> On Thu, 26 Apr 2018 17:29:17 +1000
> Steven D'Aprano  wrote:
>> On Thu, Apr 26, 2018 at 07:16:28PM +1200, Greg Ewing wrote:
>> > Tim Peters wrote:
>> > >As a statement in a program (as opposed to typed at a shell),
>> > >"a := 3" has the unnecessary (in that context) property of returning
>> > >(and discarding 3), so it's better style to use "a = 3" in that
>> > >context.
>> >
>> > That seems like a post-hoc justification. If := were the one
>> > and only assignment symbol, the compiler could easily optimise
>> > away the extra DUP_TOP or whatever is involved.
>>
>> Its still bad form to rely on compiler-dependent optimizations which
>> aren't part of the language specification.
>
> If such were the need, you could very well make it part of the language
> specification.  We are talking about a trivial optimization that any
> runtime could easily implement (e.g. if a sequence `DUP_TOP, STORE_FAST,
> POP_TOP` occurs, replace it with `STORE_FAST`).

Not at the REPL, no. At the REPL, you need to actually print out that
value. It's semantically different.

> Any runtime already has to implement a set of performance properties
> that's far less trivial than that.  For example, any decent runtime is
> expected to provide amortized O(1) list append or dict insertion.  You
> are breaking user expectations if you don't.

You assume that, but it isn't always the case. Did you know, for
instance, that string subscripting (an O(1) operation in CPython) is
allowed to be O(n) in other Python implementations?

Now you do.

ChrisA
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 573 -- Module State Access from C Extension Methods

2018-04-26 Thread Jeroen Demeyer

- In Python code, __objclass__ should be the defining class, not the module.


Indeed. My idea would be to add an accessor __parent__ returning the 
m_parent field (whatever it is) and then implement __objclass__ as 
something like:


@property
def __objclass__(self):
parent = getattr(self, "__parent__", None)
if isinstance(parent, type):
return parent
else:
raise AttributeError

In PEP 575, I don't plan to add a Python attribute specifically for 
getting the defining module: I'll leave that to PEP 573.

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Antoine Pitrou
On Thu, 26 Apr 2018 15:34:17 +1000
Steven D'Aprano  wrote:

> On Thu, Apr 26, 2018 at 05:22:58PM +1200, Greg Ewing wrote:
> > Łukasz Langa wrote:  
> > >What was its own assignment before
> > >now is part of the logic test. This saves on vertical whitespace but makes
> > >parsing and understanding logic tests harder.  
> > 
> > Another way to say this is that expressions are no longer
> > restricted to being trees, but can be general DAGs, which
> > require more mental effort to understand.  
> 
> Is that right? I presume you mean that there can be cycles in 
> expressions involving binding-expressions. If not, what do you mean?
> 
> Can you give an example of a Python expression, involving PEP 572 
> binding-expressions, that is not a tree but a more general DAG or that 
> contains cycles?

Depends if you mean a graph between names or values?

If between names, you can even have cycles AFAICT:

  ((a: = a + b), (b: = a))

Regards

Antoine.


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Antoine Pitrou
On Thu, 26 Apr 2018 17:29:17 +1000
Steven D'Aprano  wrote:
> On Thu, Apr 26, 2018 at 07:16:28PM +1200, Greg Ewing wrote:
> > Tim Peters wrote:  
> > >As a statement in a program (as opposed to typed at a shell),
> > >"a := 3" has the unnecessary (in that context) property of returning
> > >(and discarding 3), so it's better style to use "a = 3" in that
> > >context.  
> > 
> > That seems like a post-hoc justification. If := were the one
> > and only assignment symbol, the compiler could easily optimise
> > away the extra DUP_TOP or whatever is involved.  
> 
> Its still bad form to rely on compiler-dependent optimizations which 
> aren't part of the language specification.

If such were the need, you could very well make it part of the language
specification.  We are talking about a trivial optimization that any
runtime could easily implement (e.g. if a sequence `DUP_TOP, STORE_FAST,
POP_TOP` occurs, replace it with `STORE_FAST`).

Any runtime already has to implement a set of performance properties
that's far less trivial than that.  For example, any decent runtime is
expected to provide amortized O(1) list append or dict insertion.  You
are breaking user expectations if you don't.

> And to steal an earlier idea from Tim, it is especially unfortunate if 
> you copy
> 
> data := sorted(huge_list_with_billions_of_items)
> 
> from a program and paste it into your REPL, then can't type again for an 
> hour or two.

Well, how do languages where assignment is an expression returning the
assigned value make their REPLs work?  I'm sure they don't inflict that
on their users, so it's certainly a solvable problem.

(abstractly: if the user is executing a top-level assignment expression,
don't display the assignment result)

> The longer I think about this, the more I am convinced that having two 
> forms of assignment, one a statement with no return value and the other 
> an expression with a return value, is a feature, not a wart or bug.

Yet, curiously, no other language seems to replicate that "feature" :-)

It's nice to innovate, but being the only one to do something may very
well mean that you're doing something ridiculous.

Regards

Antoine.


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 572: Write vs Read, Understand and Control Flow

2018-04-26 Thread Nathaniel Smith
On Wed, Apr 25, 2018 at 11:53 PM, Chris Angelico  wrote:
> Well, true. The point isn't WHO you're dictating to, but that you can
> dictate it at all. "Hmm, let's see. Toss a 'foo colon-equals' in front
> of X, then print out what foo is." My day job involves a lot of
> helping students learn how to debug, so I say this kind of thing a lot
> (even if it's obvious to me what the problem is, because the student
> needs to learn debugging, not just be told what to fix). Refactoring
> just for the sake of a print call is overkill and potentially risky
> (if the student edits the wrong thing).

This is overstating things slightly... the best alternative to 'foo
colon-equals' isn't risky refactoring so you can call print, it's a
helper like:

def p(obj):
print(obj)
return obj

that you can sprinkle inside existing expressions.

Expecting new users to realize that this is possible, and a good idea,
and to implement it, and get it right, while they're in the middle of
being confused about basic python things, is not terribly reasonable,
so it's probably underused. But there are ways we could address that.

-n

-- 
Nathaniel J. Smith -- https://vorpus.org
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Antoine Pitrou
On Wed, 25 Apr 2018 18:52:34 -0700
Łukasz Langa  wrote:
> > On 25 Apr, 2018, at 5:20 PM, Chris Angelico  wrote:
> > 
> > On Thu, Apr 26, 2018 at 10:11 AM, Yury Selivanov
> >  wrote:  
> >> Just yesterday this snippet was used on python-dev to show how great the
> >> new syntax is:
> >> 
> >>  my_func(arg, buffer=(buf := [None]*get_size()), size=len(buf))
> >> 
> >> To my eye this is an anti-pattern.  One line of code was saved, but the
> >> other line becomes less readable.  The fact that 'buf' can be used after
> >> that line means that it will be harder for a reader to trace the origin of
> >> the variable, as a top-level "buf = " statement would be more visible.  
> > 
> > Making 'buf' more visible is ONLY a virtue if it's going to be used
> > elsewhere. Otherwise, the name 'buf' is an implementation detail of
> > the fact that this function wants both a buffer and a size.  
> 
> You're claiming that `:=` is nicer in this situation because it's less
> prominent than regular assignment and thus doesn't suggest that the name
> stays visible later.
> 
> But as others said, `:=` *does* make the name visible later until the
> enclosing scope ends.  In fact, a large part of its appeal is that you
> can use the result later (as in the `re.search()` example).  Will it be
> visible enough to the reaser in those cases then?
> 
> There seems to be a conflict there.

Not only, but seeing `:=` hints that something *special* is going on
(some inner expression is being bound to a name). So now we have to be
extra careful when reading and reviewing code written that people who
like using that syntactical feature.

I also wonder how long it will be before someone writes:

def f(arg):
global _lazy_value
if predicate(arg) and (_lazy_value := frobnicate()) > arg:
...

(or something similar with "nonlocal")

Regards

Antoine.


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Steven D'Aprano
On Thu, Apr 26, 2018 at 03:31:13AM -0400, Terry Reedy wrote:
> On 4/25/2018 8:20 PM, Chris Angelico wrote:
> >On Thu, Apr 26, 2018 at 10:11 AM, Yury Selivanov
> > wrote:
> >>Just yesterday this snippet was used on python-dev to show how great the
> >>new syntax is:
> >>
> >>   my_func(arg, buffer=(buf := [None]*get_size()), size=len(buf))
> 
> What strikes me as awful about this example is that len(buf) is 
> get_size(), so the wrong value is being named and saved. 
> 'size=len(buf)' is, in a sense, backwards.

Terry is absolutely right, and I'm to blame for that atrocity. Mea 
culpa.

But Yury is misrepresenting the context in which I came up with that 
snippet. It was not "to show how great the new syntax is", but to try to 
give a *more realistic example of what we might right, instead of the 
toy example he had given:

Yuri claimed that 

my_func(a=(b:=foo))

was "barely readable" and I responded:


There's no advantage to using binding-expressions unless 
you're going to re-use the name you just defined, and that
re-use will give you a hint as to what is happening:

Alas, my spur of the moment example was crap, as you point out, but the 
point still stands: Yuri's example is mysterious, because there's a 
local variable b assigned to which doesn't seem to be used anywhere. It 
is either a mistake of some sort, simply poor code, or maybe b is used 
somewhere else in the function. Which seems poor style: if b is intended 
to be used elsewhere in the function, why not use normal assignment?

Using a binding expression is a hint that it is likely *intended* to 
only be used in the current expression, or block. That's not a rule 
that the compiler ought to enforce, but it is a reasonable stylistic 
idiom, like using ALLCAPS for constants. At least, that's my opinion.

So, crappy example or not, if I see a binding expression, that hints 
that the name used is needed in the current expression multiple times. 
It certainly should motivate me to look further ahead in the current 
expression to see where the newly defined variable is used next, and if 
it is only used once, to wonder if there has been some mistake.

Whereas a stand alone assignment doesn't really give any hint (apart 
from vertical proximity, which is a very poor hint) as to how often and 
where a variable is used.


-- 
Steve
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Terry Reedy

On 4/25/2018 8:20 PM, Chris Angelico wrote:

On Thu, Apr 26, 2018 at 10:11 AM, Yury Selivanov
 wrote:

Just yesterday this snippet was used on python-dev to show how great the
new syntax is:

   my_func(arg, buffer=(buf := [None]*get_size()), size=len(buf))


What strikes me as awful about this example is that len(buf) is 
get_size(), so the wrong value is being named and saved. 
'size=len(buf)' is, in a sense, backwards.


buflen  = get_size()
my_func(arg, buffer = [None]*buflen, size=buflen)

Is standard, clear Python code.  I do not see that
my_func(arg, buffer=[None]*(buflen:=get_size()), size=buflen)
is an improvement.

--
Terry Jan Reedy

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Steven D'Aprano
On Thu, Apr 26, 2018 at 07:16:28PM +1200, Greg Ewing wrote:
> Tim Peters wrote:
> >As a statement in a program (as opposed to typed at a shell),
> >"a := 3" has the unnecessary (in that context) property of returning
> >(and discarding 3), so it's better style to use "a = 3" in that
> >context.
> 
> That seems like a post-hoc justification. If := were the one
> and only assignment symbol, the compiler could easily optimise
> away the extra DUP_TOP or whatever is involved.

Its still bad form to rely on compiler-dependent optimizations which 
aren't part of the language specification.

And to steal an earlier idea from Tim, it is especially unfortunate if 
you copy

data := sorted(huge_list_with_billions_of_items)

from a program and paste it into your REPL, then can't type again for an 
hour or two.

The longer I think about this, the more I am convinced that having two 
forms of assignment, one a statement with no return value and the other 
an expression with a return value, is a feature, not a wart or bug. Yes, 
it does add some complexity to the language, but it is *useful* 
complexity. If all complexity was bad, we'd still be programming by 
flicking toggle switches.



-- 
Steve
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Greg Ewing

Tim Peters wrote:

To my eyes, this is genuinely harder to follow, despite its relative brevity:

while total != (total := total + term):


Not surprising, since there are at least two deeper levels
of subtlety at play:

1. total isn't just naming a subexpression, it's being
rebound to something that depends on its previous value.

2. Order of evaluation is being relied on to ensure that
the new value of total is compared to its old value.

--
Greg

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Greg Ewing

Tim Peters wrote:

As a statement in a program (as opposed to typed at a shell),
"a := 3" has the unnecessary (in that context) property of returning
(and discarding 3), so it's better style to use "a = 3" in that
context.


That seems like a post-hoc justification. If := were the one
and only assignment symbol, the compiler could easily optimise
away the extra DUP_TOP or whatever is involved.

--
Greg
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Tim Peters
[Raymond Hettinger ]
>>> After re-reading all the proposed code samples, I believe that
>>> adopting the PEP will make the language harder to teach to people
>>> who are not already software engineers.

[Tim]
>> Can you elaborate on that?

[Raymond]
> Just distinguishing between =, :=, and == will be a forever recurring
> discussion, far more of a source of confusion than the occasional
> question of why Python doesn't have embedded assignment.

To be clear, is distinguishing between "=" and "==" already a forever
recurring discussion in your experience?  Or are you predicting that
adding ":=" will create that situation?


> Also, it is of concern that a number of prominent core dev
> respondents to this thread have reported difficulty scanning
> the posted code samples.

Yes, it is - although some of the examples sucked ;-)


>> I've used dozens of languages over the
>> decades, most of which did have some form of embedded assignment.

> Python is special, in part, because it is not one of those languages.
> It has virtues that make it suitable even for elementary school children.
> We can show well-written Python code to non-computer folks and walk
> them through what it does without their brains melting (something I can't
> do with many of the other languages I've used).  There is a virtue
> in encouraging simple statements that read like English sentences
> organized into English-like paragraphs, presenting itself like
> "executable pseudocode".

It's certainly possible to stick to a subset of Python for which
that's true.  But I didn't mention those dozens of languages because I
seek to emulate them, but to establish that I've had decades of
experience with embedded assignments in a wide variety of languages
and language communities.


> Perl does it or C++ does it is unpersuasive.

Wasn't meant to be.


> Its omission from Python was always something that I thought Guido had
> left-out on purpose, intentionally stepping away from constructs that would
> be of help in an obfuscated Python contest.

He left out lots of stuff at first, but warmed to it later.  Probably
the most profound:  there were exactly and only 3 scopes at first:
local, global, and builtin.  Functions (for example) could still nest,
but had no way to access names local to enclosing functions save via
deep trickery.  That was a noble experiment (it was a deliberate
attempt to avoid complex scoping rules), but eventually proved too
restrictive in practice.

This is nothing compared to that ;-)  But it's a tiny bit related in
that biting the arbitrarily-deeply-nested-scopes bullet was aimed more
at experienced programmers than at newbies.  The scoping rules became
far harder to explain as a result - but far more what experienced
programmers expected.


>> Yes, I'm a software engineer, but I've always pitched in on "help
>> forums" too.

> That's not really the same.

I believe it!

>  I've taught Python to many thousands of professionals, almost
> every week for over six years.  That's given me a keen sense of
> what is hard to teach.  It's okay to not agree with my assessment,
> but I would like for fruits of my experience to not be dismissed in a
> single wisp of a sentence.

I asked you to elaborate - I didn't dismiss anything.  You merely made
a raw assertion in your original message, without enough detail to
even know _what_ it is you thought would be hard to teach.  Your
elaboration is helping.

> Any one feature in isolation is usually easy to explain, but showing
> how to combine them into readable, expressive code is another matter.

OK, so it's not binding expressions in isolation that you expect will
be hard to teach if they're added, but ... how to use them
intelligently (if ever)?  That's progress, if so.

That part I can see having major trouble with.  Even the proponents of
this PEP don't always agree with each other about which examples are
"good ones".


> And as Yuri aptly noted, we spend more time reading code than writing code.
> If some fraction of our users finds the code harder to scan
> because the new syntax, then it would be a net loss for the language.

It would be a tradeoff pitting their losses against others' gains, of
course.  I don't know how to quantify that (not even to the extent of
determining the sign bit) in advance.  I'm also at least as concerned
about - indeed - professional software engineers as beginners.


> I hesitated to join this thread because you and Guido seemed to be
> pushing back so hard against anyone's who design instincts didn't favor
> the new syntax.

That's just vigorous debate, at least on my part.  Guido gets annoyed
by emotional tirades and FUD, of which there's always plenty in
threads that have gone on for hundreds of messages (I don't know
whether you followed any of this on python-ideas, but most arguments
on python-dev were already many-times-over old by the time it first
appeared here).


> It would be nice to find some common ground and 

Re: [Python-Dev] PEP 572: Write vs Read, Understand and Control Flow

2018-04-26 Thread Chris Angelico
On Thu, Apr 26, 2018 at 3:54 PM, Stephen J. Turnbull
 wrote:
> Chris Angelico writes:
>
>  > Additionally, naming sub-parts of a large expression can assist an
>  > interactive debugger, providing useful display hooks and partial
>  > results. Without a way to capture sub-expressions inline, this
>  > would require refactoring of the original code; with assignment
>  > expressions, this merely requires the insertion of a few ``name
>  > :=`` markers. Removing the need to refactor reduces the likelihood
>  > that the code be inadvertently changed as part of debugging (a
>  > common cause of Heisenbugs),
>
> Period here preferred.
>
>  > and is easier to dictate to a student or junior programmer.
>
> True but gratuitous.  It's also true that it's easier to dictate to
> Guido or Tim, though you might be happier if you let them refactor!
>

Well, true. The point isn't WHO you're dictating to, but that you can
dictate it at all. "Hmm, let's see. Toss a 'foo colon-equals' in front
of X, then print out what foo is." My day job involves a lot of
helping students learn how to debug, so I say this kind of thing a lot
(even if it's obvious to me what the problem is, because the student
needs to learn debugging, not just be told what to fix). Refactoring
just for the sake of a print call is overkill and potentially risky
(if the student edits the wrong thing).

Feel free to suggest an alternate wording.

ChrisA
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Greg Ewing

Łukasz Langa wrote:
Ha, not in Python! Here we have *different syntax* for assignments in 
expressions. Well, you can also use it as a statement. But don't!


This is what I least like about the proposal. We should
be moving in the direction of removing warts, but here
we would be *creating* one (two different assignment
operators with overlapping use cases) that we won't be
able to get rid of without a Python 4000 (that Guido has
promised won't happen).

--
Greg
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Greg Ewing

On Thu, Apr 26, 2018 at 10:11 AM, Yury Selivanov
 wrote:


 my_func(arg, buffer=(buf := [None]*get_size()), size=len(buf))


Obviously what we want here is a variant of the binding
expression that also makes it a keyword argument:

   my_func(arg, buffer ::= [None]*get_size(), size = len(buffer))

--
Greg
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Steven D'Aprano
On Wed, Apr 25, 2018 at 10:14:11PM -0700, Łukasz Langa wrote:

> So only use the Pascal one in expressions. But don't forget 
> parentheses, otherwise it will bind the thing you probably didn't want 
> anyway.

Binding expressions are no worse than any other expression: sometimes 
you need to bracket terms to change the default precedence, and 
sometimes you don't.

And sometimes, even if we don't *need* parens, we use them anyway 
because it makes the expression easier to read and understand.

Unless you have a language with no operator precedence at all, a purely 
left-to-right evaluation order like Forth or (I think?) APL, there will 
always be circumstances where parens are needed. Criticising binding- 
expressions for that reason, especially implying that we must always use 
parens, is simply FUD.


[...]
> As soon as we have to wrap a part of an expression in parentheses, 
> parsing the entire thing becomes more complex.

Unless it becomes less complex to read and understand.

I for one always have difficulty parsing complex boolean tests unless I 
bracket some or all of the parts, even when they're not strictly needed. 
Consequently I try very hard not to write complex bool tests in the 
first place, but when I can't avoid it, a few extra brackets really 
helps simplify the logic.


> Often enough it will 
> cause the expression to exceed whatever line length limit the codebase 
> pledged not to exceed, causing one line to become three.

Just how often are your lines within two characters of the maximum 
column so that adding a pair of brackets () will "often enough" put it 
over the limit? Seems pretty unlikely to me. This sounds really like 
picking at straws.


-- 
Steve
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

2018-04-26 Thread Tim Peters
[Tim]
>> One language feature conspicuous by absence in newbie
>> confusions was, consistently, assignment expressions.  Read any book
>> or tutorial for such a language, and you'll find very little space
>> devoted to them too.

[Łukasz Langa ]
> Well, you have an entire code style built around this feature called Yoda
> conditions. You teach people on Day 1 to never ever confuse == with =. Some
> compilers even warn about this because so many people did it wrong.

Sorry, I couldn't follow that.  In languages like C that use easily
confused operator symbols, sure, people are forever typing "=" when
they mean "==".  That's nothing to do with whether they _understand_
what the different operators do, though.  They do.  In languages like
Icon (that use "=" for numeric comparison and ":=" for assignment),
that never occurs.  But I'm not sure that addressed the point you were
making.


>> What's to learn?  If they understand "binding a name" _at all_ (which
>> they must to even begin to write a non-trivial program), the only
>> twist is that a binding expression returns the value being bound.

> Ha, not in Python! Here we have *different syntax* for assignments in
> expressions.

Yes, binding expressions in the current PEP support an extremely
limited subset of what Python's assignment statements support.  That
they use different operator symbols is irrelevant to that the meaning
of "binding a name" is exactly the same for both..  _That's_ the "hard
part" to learn.


> Well, you can also use it as a statement. But don't!

Why not?  _Every_ expression in Python can be used as a statement.
Nothing forbids it, and that's even (very!) useful at an interactive
prompt.


> We have a better one for that.

As a matter of style, sure, it's best to use the simplest thing that
works.  As a statement in a program (as opposed to typed at a shell),
"a := 3" has the unnecessary (in that context) property of returning
(and discarding 3), so it's better style to use "a = 3" in that
context.


> And that one supports type annotations, can unpack and assign to many
> targets at the same time, and can even increment, multiply and so on, at once.
> But the other one can't.

So?  math.sqrt() blows up when passed -1, but cmath.sqrt() doesn't.
Different tools for different tasks.


> So only use the Pascal one in expressions. But don't forget parentheses,
> otherwise it will bind the thing you probably didn't want anyway.

[Raymond]
>>> To my eyes, the examples give ample opportunity for being
>>> misunderstood and will create a need to puzzle-out the intended
>>> semantics.

>> Some do, many don't.

> As soon as we have to wrap a part of an expression in parentheses, parsing
> the entire thing becomes more complex. Often enough it will cause the
> expression to exceed whatever line length limit the codebase pledged not to
> exceed, causing one line to become three. And again, making it trickier for
> a regular Łukasz to understand what's going on.

At this point I think you must have a lower opinion of Python
programmers than I have ;-)  If adding even a dozen characters to a
line makes it exceed a reasonable line-length guide, the code was
almost certainly too confusingly dense to begin with.  All the
binding-expression examples I've given as "improvements" had _oceans_
of horizontal white space to swim in.

Guido's if/elif/elif/elif/ ... complex text-processing example didn't,
but because the current lack of an ability to bind-and-test in one
gulp forced the `elif` parts to be ever-more-deeply-indented `if`
blocks instead.

So, to match your sarcasm, here's mine:  try using a feature for what
it's good at instead of for what it's bad at ;-)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com