Re: [Python-ideas] An alternative to PEP 572's Statement-Local Name Bindings

2018-03-02 Thread Nick Coghlan
On 3 March 2018 at 11:36, Greg Ewing  wrote:

> 1. Name bindings local to an expression:
>
>roots = ([(-b-r)/(2*a), (-b+r)/(2*a)] where r = sqrt(b*b-4*a*c))
>
> B. In an expression, surrounded by parentheses for
> disambiguation. Bindings are visible only within the
> parentheses.
>

I'll note that a significant benefit of this approach over the PEP 572
approach is that it would be amenable to a comprehension style
scope-management solution: these expressions could create an implicitly
nested function and immediately call it, just as 3.x comprehensions do.
Adopting such an approach would *dramatically* lower the impact that hiding
the bindings from the surrounding scope would have on the overall name
resolution semantics.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] An alternative to PEP 572's Statement-Local Name Bindings

2018-03-02 Thread Nick Coghlan
On 3 March 2018 at 11:36, Greg Ewing  wrote:

> PEP 572 as it stands seems to have many problems:
>
> * Asymmetry between the first and subsequent
>   uses of the bound value
> * Embedded as-clauses are subtle and hard to spot
> * Ever more convoluted semantics are being invented
>   to address percieved pitfalls
>
> Alternative proposal
> 
>
> Getting back to the original motivating use case of
> intermediate values in comprehensions, to my mind there
> is really only one clear and obvious way to write such
> things:
>
>[(f(y), g(y)) for x in things where y = h(x)]
>


I know Guido is on record as not wanting to allow both "for name in
sequence" and "for name = expr" due to that being a very subtle distinction
between iteration and simple assignment (especially given that Julia uses
them as alternate spellings for the same thing), but I'm wondering if it
may be worth considering such a distinction in *with statements*, such that
we allowed "with name = expr" in addition to "with cm as name" (where "name
= expr" is just an ordinary assignment statement that doesn't trigger the
context management protocol).

The related enhancement to comprehensions would then be to allow with
clauses to be interleaved between the for loops and the if statements, such
that you could write things like:

pairs = [(f(y), g(y)) for x in things with y = h(x)]
contents = [f.read() for fname in filenames with open(fname) as f]

while still preserving the property where comprehensions can be correctly
interpreted just by converting each of the clauses to the corresponding
statement form.

Even without the "with name = expr" change, allowing with clauses in
comprehensions would let you do (by way of a suitably defined "bind" CM):

pairs = [(f(y), g(y)) for x in things with bind(h(x)) as y]

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572: Statement-Local Name Bindings

2018-03-02 Thread Nick Coghlan
On 3 March 2018 at 03:51, Ethan Furman  wrote:

> On 03/02/2018 02:47 AM, Nick Coghlan wrote:
>
>> On 2 March 2018 at 16:39, Ethan Furman wrote:
>>
>>> On 03/01/2018 09:08 PM, Nick Coghlan wrote:
>>>
>>
> Adding statement local variables into that mix *without* some form of
 syntactic marker would mean taking an already
 complicated system, and making it even harder to reason about correctly
 (especially if statement locals interact
 with nested scopes differently from the way other locals in the same
 scope do).

>>>
>>> Seems like it would far easier and (IMHO) more useful to scale the
>>> proposal back from a statement scope to simple
>>> expression assignment, and the variable is whatever scope it would have
>>> been if assigned to outside the expression
>>> (default being local, but non-local or global if already declared as
>>> such).
>>>
>>
>> Because that would put us back in the exact same problematic situation we
>> had when "[x*x for x in sequence]" leaked the
>> iteration variable (only worse): no function locals would be safe, since
>> arbitrary expressions could clobber them, not
>> just name binding operations (assignment, import statements, for loops,
>> with statements, exception handlers, class and
>> function definitions).
>>
>
> Ah, right.  Since the PEP primarily covers comprehensions, but then went
> on to discuss multi-line statements, I had forgotten the comprehension
> part.  The answer is easy:  assignment expressions in comprehensions stay
> inside comprehensions, just like other inner comprehension variables
> already do (function sub-scope, after all).  Thank you for pointing that
> out.
>

That wasn't the point I was try to make: my attempted point was that I see
allowing an expression like "print((f() as x), x^2, x^3)" to overwrite the
regular function local "x" as being just as unacceptable as "data = [x^2
for x in sequence]" overwriting it, and we already decided that the latter
was sufficiently undesirable that we were willing to break backwards
compatibility in order to change it.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572: Statement-Local Name Bindings

2018-03-02 Thread Nick Coghlan
On 3 March 2018 at 10:09, Greg Ewing  wrote:

> Nick Coghlan wrote:
>
>> I don't think it should be possible to close over statement locals.
>>
>
> Why not?


I gave a more detailed answer to that in
https://mail.python.org/pipermail/python-ideas/2018-March/049138.html, but
the short version is:

* prohibiting closing over them opens up a lot of opportunities to simplify
the implementation
* prohibiting closing over them increase their semantic distance from
regular function locals, making it easier for people to answer the question
"Should I use a function local or a statement local?" in the future

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Chris Angelico
On Sat, Mar 3, 2018 at 12:48 PM, Greg Ewing  wrote:
> Chris Angelico wrote:
>>
>> It would NOT work for anything where the bool() of
>> the desired object doesn't exactly match the loop's condition.
>
>
>while condition(x) where x = something():
>   ...
>

And we're back to needing a new keyword. Though this is reasonably
plausible, so I could add it to the PEP (as another rejected
alternative) if there's support for it.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] An alternative to PEP 572's Statement-Local Name Bindings

2018-03-02 Thread Robert Vanden Eynde
The syntax you propose is already in the Alternate syntax and there is an
implementation at https://github.com/thektulu/cpython/tree/where-expr

Already discussed, but no conclusion, for me I see two different proposals,
the "[y for x in range(5) with y = x+1]" in comprehensions list, and the
case in any expression "print (y with y = x+1)", as discussed the second
case corresponds to a simple assignment so is less useful, but if the scope
is local to the expression, that'd be useful : print(y with y = x+1);
print(y) # NameError

But I like it :)

Le 3 mars 2018 02:36, "Greg Ewing"  a écrit :

> PEP 572 as it stands seems to have many problems:
>
> * Asymmetry between the first and subsequent
>   uses of the bound value
> * Embedded as-clauses are subtle and hard to spot
> * Ever more convoluted semantics are being invented
>   to address percieved pitfalls
>
> Alternative proposal
> 
>
> Getting back to the original motivating use case of
> intermediate values in comprehensions, to my mind there
> is really only one clear and obvious way to write such
> things:
>
>[(f(y), g(y)) for x in things where y = h(x)]
>
> Possible objections to this:
>
> * Requires a new keyword, which may break existing code.
>
> - Yes, but "where" is an unlikely choice of name, being
> neither a noun, verb or adjective, so it probably wouldn't
> break very *much* code. In return, we get something that
> resonates with language mathematicians have been using
> for centuries, and a word that can be usefully googled.
>
> * Out-of-order evaluation
>
> - Comprehensions and if-expressions already have that.
>
> Extension to other use cases
> 
>
> There are some other situations in which it could be
> useful to have a similar construct.
>
> 1. Name bindings local to an expression:
>
>roots = ([(-b-r)/(2*a), (-b+r)/(2*a)] where r = sqrt(b*b-4*a*c))
>
> 2. Names bound as part of an expression and also available
> in a following suite:
>
>if m where m = pattern.match(text):
>   do_something_with(m)
>
> There's a problem, though -- if "where" in an expression
> creates bindings local to that expression, they're not
> going to be visible in the rest of a comprehension or
> compound statement.
>
> So I'm thinking that there would actually be three distinct
> usages of "where":
>
> A. As a clause in a comprehension, where it creates bindings
> local to the comprehension and is treated on the same footing
> syntactically as "for" and "if" clauses.
>
> B. In an expression, surrounded by parentheses for
> disambiguation. Bindings are visible only within the
> parentheses.
>
> C. Following the expression of an "if" or "while" statement.
> Bindings are visible within the preceding expression and the
> following suite.
>
> Note that case B avoids the issue of whether expression-local
> bindings affect the LHS of an assignment, because in
>
>a[x] = (x * 2 where x = 17)
>
> the "x" bound by the where-clause is clearly restricted to
> the part in parentheses. This would be a syntax error:
>
>a[x] = x * 2 where x = 17# illegal
>
> --
> Greg
>
>
>
>
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572: Statement-Local Name Bindings

2018-03-02 Thread Greg Ewing

Nick Coghlan wrote:
I don't think it should be possible to close over 
statement locals.


Why not?

--
Greg
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Greg Ewing

Chris Angelico wrote:

It would NOT work for anything where the bool() of
the desired object doesn't exactly match the loop's condition.


   while condition(x) where x = something():
  ...

--
Greg
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] An alternative to PEP 572's Statement-Local Name Bindings

2018-03-02 Thread Greg Ewing

PEP 572 as it stands seems to have many problems:

* Asymmetry between the first and subsequent
  uses of the bound value
* Embedded as-clauses are subtle and hard to spot
* Ever more convoluted semantics are being invented
  to address percieved pitfalls

Alternative proposal


Getting back to the original motivating use case of
intermediate values in comprehensions, to my mind there
is really only one clear and obvious way to write such
things:

   [(f(y), g(y)) for x in things where y = h(x)]

Possible objections to this:

* Requires a new keyword, which may break existing code.

- Yes, but "where" is an unlikely choice of name, being
neither a noun, verb or adjective, so it probably wouldn't
break very *much* code. In return, we get something that
resonates with language mathematicians have been using
for centuries, and a word that can be usefully googled.

* Out-of-order evaluation

- Comprehensions and if-expressions already have that.

Extension to other use cases


There are some other situations in which it could be
useful to have a similar construct.

1. Name bindings local to an expression:

   roots = ([(-b-r)/(2*a), (-b+r)/(2*a)] where r = sqrt(b*b-4*a*c))

2. Names bound as part of an expression and also available
in a following suite:

   if m where m = pattern.match(text):
  do_something_with(m)

There's a problem, though -- if "where" in an expression
creates bindings local to that expression, they're not
going to be visible in the rest of a comprehension or
compound statement.

So I'm thinking that there would actually be three distinct
usages of "where":

A. As a clause in a comprehension, where it creates bindings
local to the comprehension and is treated on the same footing
syntactically as "for" and "if" clauses.

B. In an expression, surrounded by parentheses for
disambiguation. Bindings are visible only within the
parentheses.

C. Following the expression of an "if" or "while" statement.
Bindings are visible within the preceding expression and the
following suite.

Note that case B avoids the issue of whether expression-local
bindings affect the LHS of an assignment, because in

   a[x] = (x * 2 where x = 17)

the "x" bound by the where-clause is clearly restricted to
the part in parentheses. This would be a syntax error:

   a[x] = x * 2 where x = 17# illegal

--
Greg




___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Robert Vanden Eynde
Le 2 mars 2018 22:21, "Robert Vanden Eynde"  a écrit :

Le 2 mars 2018 22:13, "Chris Angelico"  a écrit :

On Sat, Mar 3, 2018 at 7:47 AM, Robert Vanden Eynde
 wrote:
>> And please, don't top-post. Again, if your mail client encourages top
>> posting, either override it, or get a better one.
>
> @Chris @Rohdri (@Jonathan below)
>
> For morons like me who didn't know what "top-posting" was, I went on
> Wikipedia (https://en.m.wikipedia.org/wiki/Posting_style).

As Ethan says, not a moron. (Though the way he put it, he sounded like
Wheatley... and if you don't know what I'm talking about, check out
Portal and Portal 2, they're games well worth playing.) One of the
beauties of text is that it's easy to research; if someone drops a
term like "top-posting", you key that into your search engine, and
voila, extra information. This is another advantage of separate
standards and common conventions. Everything works with everything
else, because it is simple and because nobody has to do everything
themselves. How do you use git to manage your CPython source tree?
It's exactly the same as using git for anything else, so you don't
need Python-specific information, just git-specific information. How
do you use a mailing list to discuss proposed language changes in
Python? Again, it's generic stuff about mailing lists, so you don't
need anything from Python. This is why we work with open standards.
Email and mailing lists are an important part of this.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


As said on the Wikipedia page I shared,

"""

For a long time the traditional style was to post the answer below as much
of the quoted original as was necessary to understand the reply (bottom or
inline). Many years later, when email became widespread in business
communication, it became a widespread practice to reply above the entire
original and leave it (supposedly untouched) below the reply.

While each online community
 differs on which styles
are appropriate or acceptable, within some communities the use of the
“wrong” method risks being seen as a breach of netiquette
, and can provoke vehement
response from community regulars.
"""

De-facto I wouldn't know which convention (of course now I clearly prefer
"interleaved posting" for obvious reason... Now that I know how to do it)
so a Manual or HowTo when signing in would be an idea :)

Of course, I clearly prefer interleaved posting for obvious reasons...  now
that I know how to produce it using my daily mail client.


Damn it, I forgot to erase the first paragraph, I'm used to forum app where
you can quickly edit a sent message when nobody already read it.

By the way, yes, text is wonderful, searchable and archivable, that's one
of the reasons to love programming and markup language :)
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Eric Fahlgren
On Fri, Mar 2, 2018 at 12:20 PM, Chris Angelico  wrote:

> How often do you have a loop like this where you actually want to
> capture the exact condition? I can think of two: regular expressions
> (match object or None), and socket read (returns empty string on EOF).
> This simplified form is ONLY of value in that sort of situation; as
> soon as you want to add a condition around it, this stops working (you
> can't say "while do_something() is not _sentinel as x:" because all
> you'll get is True). And if you are looking for one specific return
> value as your termination signal, you can write "for x in
> iter(do_something, None):".
>

​For me, it's all the time.  Our geometry modeling database is
hierarchical, so you see things like this all over kernel, often with a lot
more code than just that one line calculating the cumulative scale factor:

>>> scale = self.scale
>>> parent = self.parent
>>> while parent:
>>> scale​ *= parent.scale
>>> parent = parent.parent  # The DRY part that I don't like...

which would turn into

>>> scale = self.scale
>>> parent = self
>>> while parent.parent as parent:
>>> scale​ *= parent.scale
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Robert Vanden Eynde
Le 2 mars 2018 22:13, "Chris Angelico"  a écrit :

On Sat, Mar 3, 2018 at 7:47 AM, Robert Vanden Eynde
 wrote:
>> And please, don't top-post. Again, if your mail client encourages top
>> posting, either override it, or get a better one.
>
> @Chris @Rohdri (@Jonathan below)
>
> For morons like me who didn't know what "top-posting" was, I went on
> Wikipedia (https://en.m.wikipedia.org/wiki/Posting_style).

As Ethan says, not a moron. (Though the way he put it, he sounded like
Wheatley... and if you don't know what I'm talking about, check out
Portal and Portal 2, they're games well worth playing.) One of the
beauties of text is that it's easy to research; if someone drops a
term like "top-posting", you key that into your search engine, and
voila, extra information. This is another advantage of separate
standards and common conventions. Everything works with everything
else, because it is simple and because nobody has to do everything
themselves. How do you use git to manage your CPython source tree?
It's exactly the same as using git for anything else, so you don't
need Python-specific information, just git-specific information. How
do you use a mailing list to discuss proposed language changes in
Python? Again, it's generic stuff about mailing lists, so you don't
need anything from Python. This is why we work with open standards.
Email and mailing lists are an important part of this.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


As said on the Wikipedia page I shared,

"""

For a long time the traditional style was to post the answer below as much
of the quoted original as was necessary to understand the reply (bottom or
inline). Many years later, when email became widespread in business
communication, it became a widespread practice to reply above the entire
original and leave it (supposedly untouched) below the reply.

While each online community
 differs on which styles
are appropriate or acceptable, within some communities the use of the
“wrong” method risks being seen as a breach of netiquette
, and can provoke vehement
response from community regulars.
"""

De-facto I wouldn't know which convention (of course now I clearly prefer
"interleaved posting" for obvious reason... Now that I know how to do it)
so a Manual or HowTo when signing in would be an idea :)

Of course, I clearly prefer interleaved posting for obvious reasons...  now
that I know how to produce it using my daily mail client.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Chris Angelico
On Sat, Mar 3, 2018 at 7:47 AM, Robert Vanden Eynde
 wrote:
>> And please, don't top-post. Again, if your mail client encourages top
>> posting, either override it, or get a better one.
>
> @Chris @Rohdri (@Jonathan below)
>
> For morons like me who didn't know what "top-posting" was, I went on
> Wikipedia (https://en.m.wikipedia.org/wiki/Posting_style).

As Ethan says, not a moron. (Though the way he put it, he sounded like
Wheatley... and if you don't know what I'm talking about, check out
Portal and Portal 2, they're games well worth playing.) One of the
beauties of text is that it's easy to research; if someone drops a
term like "top-posting", you key that into your search engine, and
voila, extra information. This is another advantage of separate
standards and common conventions. Everything works with everything
else, because it is simple and because nobody has to do everything
themselves. How do you use git to manage your CPython source tree?
It's exactly the same as using git for anything else, so you don't
need Python-specific information, just git-specific information. How
do you use a mailing list to discuss proposed language changes in
Python? Again, it's generic stuff about mailing lists, so you don't
need anything from Python. This is why we work with open standards.
Email and mailing lists are an important part of this.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Robert Vanden Eynde
Le 2 mars 2018 22:03, "Ethan Furman"  a écrit :

On 03/02/2018 12:47 PM, Robert Vanden Eynde wrote:

@Chris @Rohdri (@Jonathan below)
>
> For morons like me who didn't know what "top-posting" was, I went on
> Wikipedia
> (https://en.m.wikipedia.org/wiki/Posting_style <
> https://en.m.wikipedia.org/wiki/Posting_style>).
>

You looked it up and researched it, so definitely NOT a moron.  ;)


I think newcomers to mailing list aren't supposed to know all those "de
> facto standard" (they never used mailing list
> before ? And I'm 25 years old, not 12), so please don't tell "our mail
> client is bad, get a new one", I'm using gmail on
> Android and gmail on Google.com, that's like, very standard.
>

Standard, maybe.  Good for basic email discussion, nevermind mailing
lists?  Nope  (My humble opinion, of course.)


But if you have other mail clients to suggest me, to configure my user
> interface, feel free to help me, but they will
> always be people not knowing these good mailing practice (is using html
> mail a bad practice too ? It used to be).
>

The Python mailing lists are plain-text, so html-mail is not great.


That's why moving to MM3 so that newcomers can use tool a bit more familiar
> like a forum and will not make the same
> "mistakes" (top posting, reply only to sender...) over and over again is a
> good thing. As someone said in their mail
> comparing web-based to mail, mailing needs configuration.
>

Most things worth using require configuration/customization (cars,
kitchens, and definitely software).

Thanks for persevering!

--
~Ethan~

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Configuration is awesome but having good default helps you not having to
tell everyone "configure that, the default is bad" (the "no send duplicate"
settings maybe changed default or you misclicked on it).

I'm just saying, be comprehensive to newcomer making mistakes, or give them
a good man to read when they sign in :)
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Chris Angelico
On Sat, Mar 3, 2018 at 7:31 AM, Brendan Barnwell  wrote:
> On 2018-03-02 12:20, Chris Angelico wrote:
>>
>> On Sat, Mar 3, 2018 at 7:04 AM, Eric Fahlgren 
>> wrote:
>>>
>>>
>>> On Fri, Mar 2, 2018 at 10:27 AM, Jelle Zijlstra
>>> 
>>> wrote:



 I wonder if we could have a more limited change to the language that
 would
 allow only the as/while use cases. Specifically, that means we could do:

 while do_something() as x:
 print(x)
>>>
>>>
>>>
>>> The "while" case is the only part of the PEP that has any traction with
>>> me.
>>> It doesn't add any keywords, scope can be identical to "with" and it
>>> cleans
>>> up a code pattern that is very common.
>>
>>
>> How often do you have a loop like this where you actually want to
>> capture the exact condition? I can think of two: regular expressions
>> (match object or None), and socket read (returns empty string on EOF).
>> This simplified form is ONLY of value in that sort of situation; as
>> soon as you want to add a condition around it, this stops working (you
>> can't say "while do_something() is not _sentinel as x:" because all
>> you'll get is True). And if you are looking for one specific return
>> value as your termination signal, you can write "for x in
>> iter(do_something, None):".
>
>
> But you could have "while (do_something() as x) is not _sentinel".
> Not sure how proponents and opponents would react to that.  Limiting the
> SLNB to the beginning of block-level statements seems perverse in a way, but
> also might cut down on gratuitous overuse mixed into all kinds of weird
> positions in statements.
>

If we're going to have something that's syntactically valid in an
expression, I don't see a lot of value in requiring that it be inside
a while or if header. That just leads to confusion and mess down the
road.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Ethan Furman

On 03/02/2018 12:47 PM, Robert Vanden Eynde wrote:


@Chris @Rohdri (@Jonathan below)

For morons like me who didn't know what "top-posting" was, I went on Wikipedia
(https://en.m.wikipedia.org/wiki/Posting_style 
).


You looked it up and researched it, so definitely NOT a moron.  ;)


I think newcomers to mailing list aren't supposed to know all those "de facto 
standard" (they never used mailing list
before ? And I'm 25 years old, not 12), so please don't tell "our mail client is 
bad, get a new one", I'm using gmail on
Android and gmail on Google.com, that's like, very standard.


Standard, maybe.  Good for basic email discussion, nevermind mailing lists?  
Nope  (My humble opinion, of course.)


But if you have other mail clients to suggest me, to configure my user 
interface, feel free to help me, but they will
always be people not knowing these good mailing practice (is using html mail a 
bad practice too ? It used to be).


The Python mailing lists are plain-text, so html-mail is not great.


That's why moving to MM3 so that newcomers can use tool a bit more familiar 
like a forum and will not make the same
"mistakes" (top posting, reply only to sender...) over and over again is a good 
thing. As someone said in their mail
comparing web-based to mail, mailing needs configuration.


Most things worth using require configuration/customization (cars, kitchens, 
and definitely software).

Thanks for persevering!

--
~Ethan~
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Robert Vanden Eynde
Le 2 mars 2018 21:02, "Chris Angelico"  a écrit :

On Sat, Mar 3, 2018 at 6:55 AM, Robert Vanden Eynde
 wrote:
> @Rhodri, this is what Everybody does because you hit the "reply to all"
> button, but, we don't receive two copies on the mail, I don't know why
(but
> that's a good thing).
>
> Le 2 mars 2018 20:48, "Rhodri James"  a écrit :
>
> On 02/03/18 18:27, Jelle Zijlstra wrote:
>>
>> 2018-03-02 7:03 GMT-08:00 Robert Vanden Eynde :
>
>
> Guys, please don't email to me *and* the mailing list.  Getting two copies
> of your deathless prose makes me less likely to pay attention to you, not
> more.
>

If you're using a poor-quality mail client, you may have to fix things
manually. (Or get a better mail client - it's up to you.) If
"Reply-All" sends to both the sender and the list, either look for a
"Reply-List" button, or manually delete the sender's address and post
only to the list.

And please, don't top-post. Again, if your mail client encourages top
posting, either override it, or get a better one.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


@Chris @Rohdri (@Jonathan below)

For morons like me who didn't know what "top-posting" was, I went on
Wikipedia (https://en.m.wikipedia.org/wiki/Posting_style).

I think newcomers to mailing list aren't supposed to know all those "de
facto standard" (they never used mailing list before ? And I'm 25 years
old, not 12), so please don't tell "our mail client is bad, get a new one",
I'm using gmail on Android and gmail on Google.com, that's like, very
standard.

But if you have other mail clients to suggest me, to configure my user
interface, feel free to help me, but they will always be people not knowing
these good mailing practice (is using html mail a bad practice too ? It
used to be).

That's why moving to MM3 so that newcomers can use tool a bit more familiar
like a forum and will not make the same "mistakes"  (top posting, reply
only to sender...) over and over again is a good thing. As someone said in
their mail comparing web-based to mail, mailing needs configuration.

@Jonathan, thanks for the settings, I didn't know about it, it solves this
common problem !
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Brendan Barnwell

On 2018-03-02 12:20, Chris Angelico wrote:

On Sat, Mar 3, 2018 at 7:04 AM, Eric Fahlgren  wrote:


On Fri, Mar 2, 2018 at 10:27 AM, Jelle Zijlstra 
wrote:



I wonder if we could have a more limited change to the language that would
allow only the as/while use cases. Specifically, that means we could do:

while do_something() as x:
print(x)



The "while" case is the only part of the PEP that has any traction with me.
It doesn't add any keywords, scope can be identical to "with" and it cleans
up a code pattern that is very common.


How often do you have a loop like this where you actually want to
capture the exact condition? I can think of two: regular expressions
(match object or None), and socket read (returns empty string on EOF).
This simplified form is ONLY of value in that sort of situation; as
soon as you want to add a condition around it, this stops working (you
can't say "while do_something() is not _sentinel as x:" because all
you'll get is True). And if you are looking for one specific return
value as your termination signal, you can write "for x in
iter(do_something, None):".


	But you could have "while (do_something() as x) is not _sentinel".  Not 
sure how proponents and opponents would react to that.  Limiting the 
SLNB to the beginning of block-level statements seems perverse in a way, 
but also might cut down on gratuitous overuse mixed into all kinds of 
weird positions in statements.


--
Brendan Barnwell
"Do not follow where the path may lead.  Go, instead, where there is no 
path, and leave a trail."

   --author unknown
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Chris Angelico
On Sat, Mar 3, 2018 at 7:04 AM, Eric Fahlgren  wrote:
>
> On Fri, Mar 2, 2018 at 10:27 AM, Jelle Zijlstra 
> wrote:
>>
>>
>> I wonder if we could have a more limited change to the language that would
>> allow only the as/while use cases. Specifically, that means we could do:
>>
>> while do_something() as x:
>> print(x)
>
>
> The "while" case is the only part of the PEP that has any traction with me.
> It doesn't add any keywords, scope can be identical to "with" and it cleans
> up a code pattern that is very common.

How often do you have a loop like this where you actually want to
capture the exact condition? I can think of two: regular expressions
(match object or None), and socket read (returns empty string on EOF).
This simplified form is ONLY of value in that sort of situation; as
soon as you want to add a condition around it, this stops working (you
can't say "while do_something() is not _sentinel as x:" because all
you'll get is True). And if you are looking for one specific return
value as your termination signal, you can write "for x in
iter(do_something, None):".

> Every one of these comprehension examples has me scratching my head,
> thinking back a couple hundred (thousand? :) ) posts to Barry's quip,
> "Sometimes a for loop is just better" (or something along those lines).

True, but there's a code smell to an unrolled 'for' loop that could
have been a comprehension had it not been for one trivial point of
pedantry. So there are advantages and disadvantages to each.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Eric Fahlgren
On Fri, Mar 2, 2018 at 10:27 AM, Jelle Zijlstra 
wrote:

>
> I wonder if we could have a more limited change to the language that would
> allow only the as/while use cases. Specifically, that means we could do:
>
> while do_something() as x:
> print(x)
>

​The "while" case is the only part of the PEP that has any traction with
me.  It doesn't add any keywords, scope can be identical to "with" and it
cleans up a code pattern that is very common.​

Every one of these comprehension examples has me scratching my head,
thinking back a couple hundred (thousand? :) ) posts to Barry's quip,
"Sometimes a for loop is just better" (or something along those lines).
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Jonathan Goble
On Fri, Mar 2, 2018 at 2:56 PM Robert Vanden Eynde 
wrote:

> @Rhodri, this is what Everybody does because you hit the "reply to all"
> button, but, we don't receive two copies on the mail, I don't know why (but
> that's a good thing).
>
> Le 2 mars 2018 20:48, "Rhodri James"  a écrit :
>
> On 02/03/18 18:27, Jelle Zijlstra wrote:
>
>> 2018-03-02 7:03 GMT-08:00 Robert Vanden Eynde :
>>
>
> Guys, please don't email to me *and* the mailing list.  Getting two copies
> of your deathless prose makes me less likely to pay attention to you, not
> more.
>
>
> --
> Rhodri James *-* Kynesim Ltd
>
>
*de-lurks* There is an option in your personal settings for the list to
choose whether to receive duplicate copies of messages sent to both you and
the list. It is usually wise to set that to "no".

To check this option, go to
https://mail.python.org/mailman/options/python-ideas, enter your email
address and password (if you don't recall your password, just enter your
email address and click "Remind" at the bottom of the page), and click "Log
in". From there, you can change a variety of options, including the one
about receiving duplicate copies of messages aimed at both you and the list.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Chris Angelico
On Sat, Mar 3, 2018 at 6:55 AM, Robert Vanden Eynde
 wrote:
> @Rhodri, this is what Everybody does because you hit the "reply to all"
> button, but, we don't receive two copies on the mail, I don't know why (but
> that's a good thing).
>
> Le 2 mars 2018 20:48, "Rhodri James"  a écrit :
>
> On 02/03/18 18:27, Jelle Zijlstra wrote:
>>
>> 2018-03-02 7:03 GMT-08:00 Robert Vanden Eynde :
>
>
> Guys, please don't email to me *and* the mailing list.  Getting two copies
> of your deathless prose makes me less likely to pay attention to you, not
> more.
>

If you're using a poor-quality mail client, you may have to fix things
manually. (Or get a better mail client - it's up to you.) If
"Reply-All" sends to both the sender and the list, either look for a
"Reply-List" button, or manually delete the sender's address and post
only to the list.

And please, don't top-post. Again, if your mail client encourages top
posting, either override it, or get a better one.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Robert Vanden Eynde
@Rhodri, this is what Everybody does because you hit the "reply to all"
button, but, we don't receive two copies on the mail, I don't know why (but
that's a good thing).

Le 2 mars 2018 20:48, "Rhodri James"  a écrit :

On 02/03/18 18:27, Jelle Zijlstra wrote:

> 2018-03-02 7:03 GMT-08:00 Robert Vanden Eynde :
>

Guys, please don't email to me *and* the mailing list.  Getting two copies
of your deathless prose makes me less likely to pay attention to you, not
more.


-- 
Rhodri James *-* Kynesim Ltd
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Rhodri James

On 02/03/18 18:27, Jelle Zijlstra wrote:

2018-03-02 7:03 GMT-08:00 Robert Vanden Eynde :


Guys, please don't email to me *and* the mailing list.  Getting two 
copies of your deathless prose makes me less likely to pay attention to 
you, not more.


--
Rhodri James *-* Kynesim Ltd
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] breakpoint(): print(*args, **kwargs) before entering pdb

2018-03-02 Thread Zachary Ware
On Fri, Mar 2, 2018 at 12:00 PM, Carl Bordum Hansen  wrote:
> I played around with a newer Python build, but when using the new
> `breakpoint` builtin, I missed my weapon of choice: dirty print-debugging.
>
> I suggest we combine forces and make the default `sys.breakpointhook`
> forward *args and **kwargs to print before entering pdb.

You can do this for yourself by adding the following to
sitecustomize.py or similar:

import sys

def printingbreakpointhook(*args, **kwargs):
print(args, kwargs)
return sys.__breakpointhook__()

sys.breakpointhook = printingbreakpointhook


-- 
Zach
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread David Mertz
On Fri, Mar 2, 2018 at 10:44 AM, Ethan Furman  wrote:

> On 03/02/2018 09:34 AM, David Mertz wrote:
>
>> >>> with bind(sqrt(2), log(2)) as (a, b):
>> ... print(a, b, a+b)
>> 1.4142135623730951 0.6931471805599453 2.1073607429330403
>>
>> This would cover 98% of the cases that I would want with the proposed
>> statement-local name bindings.
>>
>
> Cool!  But what's the advantage over simple assignment?
>

The only difference from simple assignment is just visual and to be more
self documenting.  Basically, it just says (to me at least): "I intend to
use these name within this block, but don't care about them elsewhere."
It's sort of an informal scope without actual scoping rules.  But of
course, this is just existing Python, and anyone who wants to or doesn't is
free to use or not use that style.  In truth, I've thought about doing it
from time to time, but never actually bothered in production code, just as
a toy.


-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Chris Angelico
On Sat, Mar 3, 2018 at 5:30 AM, Brendan Barnwell  wrote:
> But if that's the case, maybe what we want is actually another thing
> that's been discussed many times on this list, namely something like a
> with-block that can define "super-local" variables that disappear at the end
> of the block:
>
> with b**2 - 4*a*c as D:
> x = [(-b + sqrt(D))/(2*a), (-b - sqrt(D))/(2*a)]
>
> This the same as my earlier version with "with", except the with
> clause comes at the beginning.
>
> There's no need to go into extreme detail here on these proposals as
> they're not really what's proposed by this PEP.

Maybe they should be. There are two halves to this proposal:

1) A syntax for capturing an expression with a name binding
2) A scoping system for statement-local names.

I'm already seeing some support for the first half without the second
("just make it a regular assignment"). Do we need two completely
separate PEPs to handle these two proposals? They could link to each
other saying "this could work well with that", but they have
independent value. Statement-local names without a syntax for name
binding would be useful in basically two contexts - the "with" syntax
given here, and "except Exception as e:", which currently uses a bit
of a weird hack of unbinding the existing name.

But the 'with' statement would then have a messy dual form. It can be
used for name bindings, and it can also be used for resource
management. The easiest way to handle this is:

def object.__enter__(self): return self
def object.__exit__(self, *a): pass

But I don't know that people want that.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Ethan Furman

On 03/02/2018 09:34 AM, David Mertz wrote:


So right now, I can do these:

class bind(object):
 def __init__(self, *args):
 self.args = args
 def __enter__(self):
 return self.args[0] if len(self.args)==1 else self.args
 def __exit__(self, *args):
 pass

 >>> with bind(sqrt(2)) as _a:
... print(_a)
1.4142135623730951

 >>> with bind(sqrt(2), log(2)) as (a, b):
... print(a, b, a+b)
1.4142135623730951 0.6931471805599453 2.1073607429330403


This would cover 98% of the cases that I would want with the proposed 
statement-local name bindings.


Cool!  But what's the advantage over simple assignment?

--
~Ethan~
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Ethan Furman

On 03/02/2018 08:04 AM, Chris Angelico wrote:

On Sat, Mar 3, 2018 at 1:53 AM, Rhodri James wrote:

On 02/03/18 11:43, Chris Angelico wrote:



  # Compound statements usually enclose everything...
  if (re.match(...) as m):
  print(m.groups(0))
  print(m) # NameError


This (and the equivalent in while loops) is the big win in the PEP, in my
opinion.  The number of ugly loops I've had to write in Python because I
can't write "while (something_to_do() as event):"...  +1 on this.


  # Using a statement-local name
  stuff = [[(f(x) as y), x/y] for x in range(5)]


As Paul said, the asymmetry of this bothers me a lot.  It doesn't read
naturally to me. -1 on this.


Interesting. I fully expected to get a lot more backlash for the
if/while usage, but a number of people are saying that that's the only
(or the biggest) part of this proposal that they like.


This is the part of the PEP that I really like as well -- far more useful to me than the list-comp examples.  I could 
even be +0.5 if the "if/while/for" compound statements were kept and the comprehensions dropped -- but not with leading 
dots -- I would rather do $ than . .  Kind of like decorators, they shouldn't be used all that often.


--
~Ethan~

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Chris Angelico
On Sat, Mar 3, 2018 at 5:27 AM, Jelle Zijlstra  wrote:
>
>
> 2018-03-02 7:03 GMT-08:00 Robert Vanden Eynde :
>>
>> +1 on extracting the big win for "if" and "while" (the regex case is
>> wonderul). It would be see as an "extended if/while" rather than a general
>> statement assignation.
>>
>
> I wonder if we could have a more limited change to the language that would
> allow only the as/while use cases. Specifically, that means we could do:
>
> while do_something() as x:
> print(x)
>
> if re.match(r'.*', text) as match:
> print(match.groups())
>
> Parentheses would no longer be necessary for syntactic ambiguity, and there
> is no real need for new scoping rules—we could just create new locals.
>
> This would alleviate some of the problems with the current proposal, such as
> complicated scoping rules and ugly syntax in comprehensions.

The trouble with this is that it's extremely restricted. It works for
the regex case, because re.match() has been specifically written to
function as either "return a match object" or "return true/false to
indicate a match", by guaranteeing to return a truthy object or None,
and nothing else. It would NOT work for anything where the bool() of
the desired object doesn't exactly match the loop's condition. For
instance, if do_something() returns None when it's done, but might
return an empty string during operation, the correct condition is
"while do_something() is not None" - and you can't capture the whole
condition any more. To be able to write "while (do_something() as x)
is not None:", you have to have the more general syntax that's used in
this PEP.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Brendan Barnwell

On 2018-03-02 03:43, Chris Angelico wrote:

After dozens of posts and a wide variety of useful opinions and
concerns being raised, here is the newest version of PEP 572 for your
debating pleasure.


	After following the discussion here, I think I've come to the 
conclusion that something like "EXPR with NAME as VALUE" is better, and 
that's because the "out-of-order" execution there is actually a benefit.


	The example that gave me the most pause in this thread was Paul Moore's 
involving the quadratic formula (slightly emended here :-):


x = [(-b + sqrt((b**2 - 4*a*c as D))/(2*a), (-b + sqrt(D)/(2*a)]

	To me this is a classic example of the kind of thing I would want to do 
with a statement-local binding, so whatever syntax is chosen won't be 
useful to me if it doesn't nicely work in situations like this.


	But I don't find the above example nice, for more or less the reason 
Paul cited: the need to assign the expression "inline" (at the point 
where it's first defined) creates an asymmetry that masks the fact that 
it's the same expression being re-used elsewhere --- and it's exactly 
that re-use that I would want to HIGHLIGHT with a statement-local binding.


The alternative with the name binding at the end is much better:

x = [(-b + sqrt(D))/(2*a), (-b - sqrt(D))/(2*a) with b**2 - 4*a*c as D]

	To my mind, it's a real desideratum for a statement-local binding that 
it should pull the bound expression OUT of the enclosing context.  The 
overall statement gains in readability only if the reader can easily see 
a shared element across multiple parts.  If I can't tell at a glance 
that the two roots both involve the same value D, there's little point 
in having a statement-local binding for it.  (It still may gain in 
computational cost, since the expression won't have to be evaluated 
multiple times, but I see that as a much less important benefit than 
readability.)


	Also note that the version above comes perilously close to the existing 
solution with a regular local variable:


D = b**2 - 4*a*c
x = [(-b + sqrt(D))/(2*a), (-b - sqrt(D))/(2*a)]

	The only difference is that now D is "leaked" to following code.  Nick 
Coghlan has argued that there's no point in an inline-assignment 
construct if it's not somehow local, since a big part of its purpose is 
to simplify reasoning by avoiding any stomping on "real" local variables.


	But if that's the case, maybe what we want is actually another thing 
that's been discussed many times on this list, namely something like a 
with-block that can define "super-local" variables that disappear at the 
end of the block:


with b**2 - 4*a*c as D:
x = [(-b + sqrt(D))/(2*a), (-b - sqrt(D))/(2*a)]

	This the same as my earlier version with "with", except the with clause 
comes at the beginning.


	There's no need to go into extreme detail here on these proposals as 
they're not really what's proposed by this PEP.  But my point is that, 
from my perspective, they have something crucial that the current 
proposal lacks: they explicitly separate the *definition* of the shared 
expression from its *use* within the statement.  Having to do the 
name-binding inline at the place where the re-used expression happens to 
occur makes the overall construct LESS readable for me, not more, so I'm 
-1 on the current proposal.


--
Brendan Barnwell
"Do not follow where the path may lead.  Go, instead, where there is no 
path, and leave a trail."

   --author unknown
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Jelle Zijlstra
2018-03-02 7:03 GMT-08:00 Robert Vanden Eynde :

> +1 on extracting the big win for "if" and "while" (the regex case is
> wonderul). It would be see as an "extended if/while" rather than a general
> statement assignation.
>
>
I wonder if we could have a more limited change to the language that would
allow only the as/while use cases. Specifically, that means we could do:

while do_something() as x:
print(x)

if re.match(r'.*', text) as match:
print(match.groups())

Parentheses would no longer be necessary for syntactic ambiguity, and there
is no real need for new scoping rules—we could just create new locals.

This would alleviate some of the problems with the current proposal, such
as complicated scoping rules and ugly syntax in comprehensions.


> +1 on list comprehensions, even if I prefer the
> [(y, x/y) with y = f(x) for x in range(5)] or [(y, x/y) for x in range(5)
> with y = f(x)] syntax (more close to "for y in [ f(x) ]".
>
> Le 2 mars 2018 15:54, "Rhodri James"  a écrit :
>
> On 02/03/18 11:43, Chris Angelico wrote:
>
>> After dozens of posts and a wide variety of useful opinions and
>> concerns being raised, here is the newest version of PEP 572 for your
>> debating pleasure.
>>
>
> I haven't said this yet, so thanks Chris for putting this all together.
> Even if the result is a rejected PEP, at least we have everything in one
> place.
>
> [snip]
>
>
>  # Compound statements usually enclose everything...
>>  if (re.match(...) as m):
>>  print(m.groups(0))
>>  print(m) # NameError
>>
>
> This (and the equivalent in while loops) is the big win in the PEP, in my
> opinion.  The number of ugly loops I've had to write in Python because I
> can't write "while (something_to_do() as event):"...  +1 on this.
>
>
>  # Using a statement-local name
>>  stuff = [[(f(x) as y), x/y] for x in range(5)]
>>
>
> As Paul said, the asymmetry of this bothers me a lot.  It doesn't read
> naturally to me. -1 on this.
>
>
> 1. What happens if the name has already been used? ``(x, (1 as x), x)``
>> Currently, prior usage functions as if the named expression did not
>> exist (following the usual lookup rules); the new name binding will
>> shadow the other name from the point where it is evaluated until the
>> end of the statement.  Is this acceptable?  Should it raise a syntax
>> error or warning?
>>
>
> I wouldn't worry too much about this case.  Anyone gratuitously reusing
> names like that deserves all that will be coming to them.
>
> Alternative proposals
>> =
>>
>> 3. ``with... as``::
>>
>> stuff = [(y, x/y) with f(x) as y for x in range(5)]
>>
>> As per option 2, but using ``as`` in place of the equals sign. Aligns
>> syntactically with other uses of ``as`` for name binding, but a simple
>> transformation to for-loop longhand would create drastically different
>> semantics; the meaning of ``with`` inside a comprehension would be
>> completely different from the meaning as a stand-alone statement.
>>
>
> Honestly I prefer this syntax for comprehensions.  It doesn't read
> perfectly but it's good enough (though I am a mathematician by original
> training, so set notation works for me anyway), and the syntax is clear and
> limited.
>
> I'm not sure the case for fully general statement-local variables has been
> made.
>
> So, counter-proposal(s):
>
> 1. Allow "(f() as a)" in the conditions of "if" and "while" statements,
> after some arguing as to whether "a" is a special snowflake or just a
> normal local variable.
>
> 2. Add a "with" clause to comprehensions to make comprehension-local
> variables (presumably the same class of thing as the iteration variables).
>
> --
> Rhodri James *-* Kynesim Ltd
>
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
>
>
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Ethan Furman

On 03/02/2018 03:43 AM, Chris Angelico wrote:


PEP: 572
Title: Syntax for Statement-Local Name Bindings
Author: Chris Angelico 


Looks nice, thanks for the updates!



Alternative proposals
=



6. Allowing ``(EXPR as NAME)`` to assign to any form of name.

This is exactly the same as the promoted proposal, save that the name is
bound in the same scope that it would otherwise have. Any expression can
assign to any name, just as it would if the ``=`` operator had been used.


Just to clarify:  "bound in the same scope" means exactly that -- if the (EXPR as NAME) is in a comprehension, then it 
is local /to that comprehension/  (emphasis because I didn't adequately convey that it my initial response to Nick).



Still -1 to the PEP as written.  (It would be positive for alternative 6. ;)

--
~Ethan~
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] breakpoint(): print(*args, **kwargs) before entering pdb

2018-03-02 Thread Carl Bordum Hansen
I played around with a newer Python build, but when using the new 
`breakpoint` builtin, I missed my weapon of choice: dirty print-debugging.


I suggest we combine forces and make the default `sys.breakpointhook` 
forward *args and **kwargs to print before entering pdb.


- Carl Bordum Hansen

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572: Statement-Local Name Bindings

2018-03-02 Thread Ethan Furman

On 03/02/2018 02:47 AM, Nick Coghlan wrote:

On 2 March 2018 at 16:39, Ethan Furman wrote:

On 03/01/2018 09:08 PM, Nick Coghlan wrote:



Adding statement local variables into that mix *without* some form of syntactic 
marker would mean taking an already
complicated system, and making it even harder to reason about correctly 
(especially if statement locals interact
with nested scopes differently from the way other locals in the same scope do).


Seems like it would far easier and (IMHO) more useful to scale the proposal 
back from a statement scope to simple
expression assignment, and the variable is whatever scope it would have been if 
assigned to outside the expression
(default being local, but non-local or global if already declared as such).


Because that would put us back in the exact same problematic situation we had when 
"[x*x for x in sequence]" leaked the
iteration variable (only worse): no function locals would be safe, since 
arbitrary expressions could clobber them, not
just name binding operations (assignment, import statements, for loops, with 
statements, exception handlers, class and
function definitions).


Ah, right.  Since the PEP primarily covers comprehensions, but then went on to discuss multi-line statements, I had 
forgotten the comprehension part.  The answer is easy:  assignment expressions in comprehensions stay inside 
comprehensions, just like other inner comprehension variables already do (function sub-scope, after all).  Thank you for 
pointing that out.



Maybe somebody could explain why a statement-local limited scope variable is 
better than an ordinary well-understood
local-scope variable?  Particularly why it's better enough to justify more 
line-noise in the syntax.  I'm willing to
be convinced (not happy to, just willing ;) .


It breaks the expectation that only a well defined subset of statement can make 
changes to local name bindings.


We already use the keyword "as" to assign names, so there is nothing extra there -- the only change is that we can now 
use it in one more place.


Are those valid counter-arguments, or is there still something I am missing?

--
~Ethan~
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread David Mertz
I remain -1 on the PEP, but thank you very much Chris for the great work
writing it and the extra clarifications in it.

The part I like most about the proposal is the use in blocks, like:

if (re.match(...) as m):
print(m.groups(0))

if (input("> ") as cmd):
def run_cmd(cmd=cmd): # Capture the value in the default arg
print("Running command", cmd) # Works


But what I like has nothing much to do with scope limitation.  It is only
about the idea of introducing a variable into a block.  We can do that with
a context manager.  No, there's no cleanup of the namespace in a
straightforward approach, but using e.g. `_x` as a convention for names
meant to be transient is already established practice and requires no
special syntax.

So right now, I can do these:

class bind(object):
def __init__(self, *args):
self.args = args
def __enter__(self):
return self.args[0] if len(self.args)==1 else self.args
def __exit__(self, *args):
pass

>>> with bind(sqrt(2)) as _a:
... print(_a)
1.4142135623730951

>>> with bind(sqrt(2), log(2)) as (a, b):
... print(a, b, a+b)
1.4142135623730951 0.6931471805599453 2.1073607429330403


This would cover 98% of the cases that I would want with the proposed
statement-local name bindings.

I suppose I could write something much more obscure that poked into the
call stack and actually deleted names from scopes in the context manager.
But really I rarely care about the temporary use of a few names, especially
if the same few temporary names are used repeatedly for these things.

On Fri, Mar 2, 2018 at 8:04 AM, Chris Angelico  wrote:

> On Sat, Mar 3, 2018 at 1:53 AM, Rhodri James  wrote:
> > On 02/03/18 11:43, Chris Angelico wrote:
> >>
> >> After dozens of posts and a wide variety of useful opinions and
> >> concerns being raised, here is the newest version of PEP 572 for your
> >> debating pleasure.
> >
> >
> > I haven't said this yet, so thanks Chris for putting this all together.
> Even
> > if the result is a rejected PEP, at least we have everything in one
> place.
>
> No problem. And I agree, a rejected PEP is still a successful result here.
>
> (Am I going to get a reputation for captaining dead PEPs?)
>
> >>  # Compound statements usually enclose everything...
> >>  if (re.match(...) as m):
> >>  print(m.groups(0))
> >>  print(m) # NameError
> >
> >
> > This (and the equivalent in while loops) is the big win in the PEP, in my
> > opinion.  The number of ugly loops I've had to write in Python because I
> > can't write "while (something_to_do() as event):"...  +1 on this.
> >
> >>  # Using a statement-local name
> >>  stuff = [[(f(x) as y), x/y] for x in range(5)]
> >
> >
> > As Paul said, the asymmetry of this bothers me a lot.  It doesn't read
> > naturally to me. -1 on this.
>
> Interesting. I fully expected to get a lot more backlash for the
> if/while usage, but a number of people are saying that that's the only
> (or the biggest) part of this proposal that they like.
>
> ChrisA
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>



-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Chris Angelico
On Sat, Mar 3, 2018 at 1:53 AM, Rhodri James  wrote:
> On 02/03/18 11:43, Chris Angelico wrote:
>>
>> After dozens of posts and a wide variety of useful opinions and
>> concerns being raised, here is the newest version of PEP 572 for your
>> debating pleasure.
>
>
> I haven't said this yet, so thanks Chris for putting this all together. Even
> if the result is a rejected PEP, at least we have everything in one place.

No problem. And I agree, a rejected PEP is still a successful result here.

(Am I going to get a reputation for captaining dead PEPs?)

>>  # Compound statements usually enclose everything...
>>  if (re.match(...) as m):
>>  print(m.groups(0))
>>  print(m) # NameError
>
>
> This (and the equivalent in while loops) is the big win in the PEP, in my
> opinion.  The number of ugly loops I've had to write in Python because I
> can't write "while (something_to_do() as event):"...  +1 on this.
>
>>  # Using a statement-local name
>>  stuff = [[(f(x) as y), x/y] for x in range(5)]
>
>
> As Paul said, the asymmetry of this bothers me a lot.  It doesn't read
> naturally to me. -1 on this.

Interesting. I fully expected to get a lot more backlash for the
if/while usage, but a number of people are saying that that's the only
(or the biggest) part of this proposal that they like.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572: Statement-Local Name Bindings

2018-03-02 Thread Robert Vanden Eynde
Sorry, answer to an old post but I just realized I didn't use the correct
email address... (See below to see which message I'm answering).

That's what I said on github, there are two different use cases : *ListComp*
 Vs *AnyExpressions* :

1) List comprehension :
[y+2 for x in range(5) for y in [ x+1 ]]
→ [y+2 for x in range(5) with y = x+1]

2) Any expression :
print(y + 2 with x = 2)

So, IF the syntax is allowed in *both* cases, then yes, the "any expression
case" would introduced a "There is not one obvious way to do it".

Now introducing *scoping*, the "any expression case" can become handy
because it would create local variables in parenthesis :

x = 2
print([y, x/y] with y = x + 2)
print(y) # NameError

It would structure expressions and would be in the same idea as PEP 3150
 but with a less drastic syntax
and more simple use case.

Maybe both cases are completely different and your we would have 3
proposals :
1) "EXPR as NAME" → to easily reuse an expression used multiple times in an
expression.
2) "EXPR with NAME = EXPR" (any expression) → same purpose, different syntax
3) "[EXPR for x in ITERABLE with NAME = EXPR] → to allow reuse of an
expression in a list comprehension.

Maybe the only use cases are in list comprehensions and would be an
improvement to the for y in [ f(x) ] not obvious syntax (that was my
original thought weeks ago and in June of last year).

Your syntax gives a proof of concept implementation
The AnyExpression case had a proof of concept in thektulu (branch
where-expr) 

Should we create "yet another pep" for each of this use cases or is it part
of a big same idea ?

Cheers,

Robert


Le 28 févr. 2018 22:53, "Chris Angelico"  a écrit :

On Thu, Mar 1, 2018 at 8:38 AM, Robert Vanden Eynde
 wrote:
> Le 28 févr. 2018 11:43, "Chris Angelico"  a écrit :
>> If you aren't using the variable multiple times, there's no point
>> giving it a name. Unless I'm missing something here?
>
> Yes, variables are not there "just because we reuse them", but also to
> include temporary variables to better understand the code.
> Same for functions, you could inline functions when used only once, but
you
> introduce them for clarity no ?

Sure, but if you're creating temporaries for clarity, you should
probably make them regular variables, not statement-local ones. If
you're going to use something only once and you don't want to break it
out into a separate statement, just use a comment.

>
> ```
> a = v ** 2 / R # the acceleration in a circular motion
> f = m * a # law of Newton
> ```
>
> could be written as
>
> ```
> f = m * (v ** 2 / R) # compute the force, trivial
> ```
>
> But having temporary variables help a lot to understand the code,
otherwise
> why would we create temporary variables ?
> I can give you an example where you do a process and each time the
variable
> is used only one.

Neither of your examples needs SLNBs.

>> Scoping is a fundamental part of both my proposal and the others I've
>> seen here. (BTW, that would be a NameError, not a SyntaxError; it's
>> perfectly legal to ask for the name 'y', it just hasn't been given any
>> value.) By my definition, the variable is locked to the statement that
>> created it, even if that's a compound statement. By the definition of
>> a "(expr given var = expr)" proposal, it would be locked to that
>> single expression.
>
> Confer the discussion on scoping on github
> (https://github.com/python/peps/commit/2b4ca20963a24cf5faac054226857e
a9705471e5)
> :
>
> """
> In the current implementation it looks like it is like a regular
assignment
> (function local then).
>
> Therefore in the expression usage, the usefulness would be debatable (just
> assign before).
>
> But in a list comprehension after the for (as I mentioned in my mail),
aka.
> when used as a replacement for for y in [ x + 1 ] this would make sense.
>
> But I think that it would be much better to have a local scope, in the
> parenthesis. So that print(y+2 where y = x + 1) wouldn't leak y. And when
> there are no parenthesis like in a = y+2 where y = x+1, it would imply
one,
> giving the same effect as a = (y+2 where y = x+1). Moreover, it would
> naturally shadow variables in the outermost scope.

So the question is: what is the benefit of the local name 'y'? In any
non-trivial example, it's not going to fit in a single line, so you
have to either wrap it as a single expression (one that's been made
larger by the "where" clause at the end), or break it out into a real
variable as a separate assignment.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
___
Python-ideas mailing list
Python-ideas@python.org

Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Robert Vanden Eynde
+1 on extracting the big win for "if" and "while" (the regex case is
wonderul). It would be see as an "extended if/while" rather than a general
statement assignation.

+1 on list comprehensions, even if I prefer the
[(y, x/y) with y = f(x) for x in range(5)] or [(y, x/y) for x in range(5)
with y = f(x)] syntax (more close to "for y in [ f(x) ]".

Le 2 mars 2018 15:54, "Rhodri James"  a écrit :

On 02/03/18 11:43, Chris Angelico wrote:

> After dozens of posts and a wide variety of useful opinions and
> concerns being raised, here is the newest version of PEP 572 for your
> debating pleasure.
>

I haven't said this yet, so thanks Chris for putting this all together.
Even if the result is a rejected PEP, at least we have everything in one
place.

[snip]


 # Compound statements usually enclose everything...
>  if (re.match(...) as m):
>  print(m.groups(0))
>  print(m) # NameError
>

This (and the equivalent in while loops) is the big win in the PEP, in my
opinion.  The number of ugly loops I've had to write in Python because I
can't write "while (something_to_do() as event):"...  +1 on this.


 # Using a statement-local name
>  stuff = [[(f(x) as y), x/y] for x in range(5)]
>

As Paul said, the asymmetry of this bothers me a lot.  It doesn't read
naturally to me. -1 on this.


1. What happens if the name has already been used? ``(x, (1 as x), x)``
> Currently, prior usage functions as if the named expression did not
> exist (following the usual lookup rules); the new name binding will
> shadow the other name from the point where it is evaluated until the
> end of the statement.  Is this acceptable?  Should it raise a syntax
> error or warning?
>

I wouldn't worry too much about this case.  Anyone gratuitously reusing
names like that deserves all that will be coming to them.

Alternative proposals
> =
>
> 3. ``with... as``::
>
> stuff = [(y, x/y) with f(x) as y for x in range(5)]
>
> As per option 2, but using ``as`` in place of the equals sign. Aligns
> syntactically with other uses of ``as`` for name binding, but a simple
> transformation to for-loop longhand would create drastically different
> semantics; the meaning of ``with`` inside a comprehension would be
> completely different from the meaning as a stand-alone statement.
>

Honestly I prefer this syntax for comprehensions.  It doesn't read
perfectly but it's good enough (though I am a mathematician by original
training, so set notation works for me anyway), and the syntax is clear and
limited.

I'm not sure the case for fully general statement-local variables has been
made.

So, counter-proposal(s):

1. Allow "(f() as a)" in the conditions of "if" and "while" statements,
after some arguing as to whether "a" is a special snowflake or just a
normal local variable.

2. Add a "with" clause to comprehensions to make comprehension-local
variables (presumably the same class of thing as the iteration variables).

-- 
Rhodri James *-* Kynesim Ltd

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Rhodri James

On 02/03/18 11:43, Chris Angelico wrote:

After dozens of posts and a wide variety of useful opinions and
concerns being raised, here is the newest version of PEP 572 for your
debating pleasure.


I haven't said this yet, so thanks Chris for putting this all together. 
Even if the result is a rejected PEP, at least we have everything in one 
place.


[snip]


 # Compound statements usually enclose everything...
 if (re.match(...) as m):
 print(m.groups(0))
 print(m) # NameError


This (and the equivalent in while loops) is the big win in the PEP, in 
my opinion.  The number of ugly loops I've had to write in Python 
because I can't write "while (something_to_do() as event):"...  +1 on this.



 # Using a statement-local name
 stuff = [[(f(x) as y), x/y] for x in range(5)]


As Paul said, the asymmetry of this bothers me a lot.  It doesn't read 
naturally to me. -1 on this.



1. What happens if the name has already been used? ``(x, (1 as x), x)``
Currently, prior usage functions as if the named expression did not
exist (following the usual lookup rules); the new name binding will
shadow the other name from the point where it is evaluated until the
end of the statement.  Is this acceptable?  Should it raise a syntax
error or warning?


I wouldn't worry too much about this case.  Anyone gratuitously reusing 
names like that deserves all that will be coming to them.



Alternative proposals
=
3. ``with... as``::

stuff = [(y, x/y) with f(x) as y for x in range(5)]

As per option 2, but using ``as`` in place of the equals sign. Aligns
syntactically with other uses of ``as`` for name binding, but a simple
transformation to for-loop longhand would create drastically different
semantics; the meaning of ``with`` inside a comprehension would be
completely different from the meaning as a stand-alone statement.


Honestly I prefer this syntax for comprehensions.  It doesn't read 
perfectly but it's good enough (though I am a mathematician by original 
training, so set notation works for me anyway), and the syntax is clear 
and limited.


I'm not sure the case for fully general statement-local variables has 
been made.


So, counter-proposal(s):

1. Allow "(f() as a)" in the conditions of "if" and "while" statements, 
after some arguing as to whether "a" is a special snowflake or just a 
normal local variable.


2. Add a "with" clause to comprehensions to make comprehension-local 
variables (presumably the same class of thing as the iteration variables).


--
Rhodri James *-* Kynesim Ltd
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572: Statement-Local Name Bindings

2018-03-02 Thread Paul Moore
On 2 March 2018 at 14:23, Nick Coghlan  wrote:
> On 2 March 2018 at 23:26, Paul Moore  wrote:
>>
>> Adding "mustn't just be another way to spell name = expr" to the
>> requirements is an extra requirement - and arguably one that
>> contradicts the original requirement which was "find a way to allow
>> name = expr in expressions".
>
>
> I consider allowing the semantic equivalent of "name = expr" as part of
> arbitrary expressions to be an anti-requirement, not a requirement, for
> three reasons:
>
> 1. It means that arbitrary statements may accidentally clobber local
> variables that we care about. We used to have this for comprehension
> iteration variables, and it was so widely deplored that we broke
> compatibility with the variable overwriting behaviour in Python 3.0.
>
> 2. It means that naming a subexpression may significantly increase the
> longevity of that reference (especially in generators and coroutines).
>
> 3. It means that naming a subexpression will define a new class or module
> attribute when used in a class or module scope
>
> Folks do sometimes *ask* for these semantics, as it's the most obvious
> behaviour to ask for when it comes to naming subexpressions, but it would be
> a really bad idea to say "yes" to those requests.
>
> Chris's PEP addresses all those potential problems:
>
> 1. Statement locals explicitly avoid overwriting regular function locals
> (although they may shadow them in the current PEP - the '.name' syntax
> avoids even that)
> 2. Statement local bindings are cleared after each statement, so they only
> significantly extend the reference lifespan when used in compound statement
> headers or directly in the same statement as a yield or await. Even in
> comprehensions they'll typically be cleared on the next loop iteration.
> 3. Statement locals aren't added to locals() or globals(), so they never
> show up as module or class attributes either
>
> The eventual conclusion may still be "The proposal adds too much additional
> complexity without an adequate corresponding gain in expressiveness", but
> that complexity does have a solid rationale behind it. (Although it may be
> worth explicitly answering "Why not use the exact same semantics as 'name =
> expr'? in the PEP itself, since it's a reasonable question to ask)

OK, understood.

Yes, I think it would be worth adding that question to the PEP. I also
think it would be worth being more explicit in the body of the PEP
over how[1] the binding of statement-local names is fundamentally
different from assignment, as that certainly wasn't obvious to me, and
may not be to others (particularly people reading it with the point of
view "This satisfies my request to allow assignment in expressions").

I don't really have much more to add in that case. I don't personally
think the added complexity is justified by the benefits, but I've
already said that and it's been noted - so thanks for helping me
understand the details of the proposal better, but it hasn't changed
my view much in the end.

Paul

[1] The "why" is covered by the question you suggested.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Chris Angelico
On Fri, Mar 2, 2018 at 10:56 PM, Paul Moore  wrote:
> On 2 March 2018 at 11:43, Chris Angelico  wrote:
>> After dozens of posts and a wide variety of useful opinions and
>> concerns being raised, here is the newest version of PEP 572 for your
>> debating pleasure.
>
> This is a distinct improvement - thanks for incorporating the varied
> feedback so well.
>
> I still remain -1, though. Reasons scattered through the other thread
> but mostly relating to the fact that there are subtle differences
> between statement-local names and other names in Python (notably that
> you can't close over them). I don't think the benefits of the proposal
> are sufficient to justify introducing a new
> similar-but-subtly-different type of name.

That's fine :) I'm under no illusions that everyone will adore this
proposal (hey, I'm no more than +0.5 on it myself). The greatest goal
of this PEP is to record the arguments for and against each of the
viable alternatives, as a long-term document.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572: Statement-Local Name Bindings

2018-03-02 Thread Stephan Houben
Hi all,

I would like to observe that there is already a way to bind names in an
expression:

a = (lambda b: [b, b])(b=f())

Currently this is not so performant, but there is nothing
stopping the compiler from special-casing such an
IIFE (Immediate Invoked Function Expression),
to use the Javascript terminology.

It would then be fast in, say, Python 3.8, but still work in earlier
versions.

Stephan



2018-03-02 14:26 GMT+01:00 Paul Moore :

> On 2 March 2018 at 12:48, Nick Coghlan  wrote:
> > The design intent related rationale stems from the fact that closed over
> > references can live for an arbitrarily long time (as can regular function
> > locals in a generator or coroutine), and I think statement locals should
> be
> > as reliably ephemeral as we can reasonably make them if they're going to
> be
> > different enough from function locals to be worth the hassle of adding
> them.
> >
> > So that means asking a bunch of questions and deliberately giving the
> > *opposite* answer for statement locals than I would for function locals:
> >
> > * Visible in locals()? Yes for function locals, no for statement locals
> > * Visible in frame.f_locals? Yes for function locals, no for statement
> > locals
> > * Prevents access to the same name in outer scopes? Yes for function
> locals,
> > no for statement locals
> > * Can be closed over? Yes for function locals, no for statement locals
> >
> > Answer "no" to all those questions is only reasonable if statement local
> > references *look* different from regular variable names. But I also
> think we
> > need to proposing answering "No" to all of them to make statement locals
> > potentially interesting enough to be worth considering.
>
> OK, that argument makes sense to me. At least in the sense that it
> makes a good case for how statement-local names should work *if* we
> adopt them. I reserve the right to change my mind, as I haven't
> thought this through fully, but at least superficially I'm with you
> this far.
>
> I will note that I don't see this as a compelling reason for *having*
> them, just a good analysis of how they might behave if we do.
>
> > Neither PEP 527 nor 3150 *needs* the syntactic markers - the compiler can
> > figure out what is going on because it does the symbol table analysis
> pass
> > before the code generation pass, and hence can tag names appropriately
> based
> > on what it finds.
> >
> > My concern is for people reading the code, where omitting a syntactic
> marker
> > also forces *humans* to read things in two passes to make sure they
> > understand them correctly. Consider this example:
> >
> > x = 10
> > data = [x*x for i in range(10)]
> >
> > This will give you a 10 item list, where each item is 100.
> >
> > But now consider a world with statement locals, where statement locals
> use
> > the same reference syntax as regular locals:
> >
> > x = 10
> > data = [x*x for i in range(10) if (12 as x)]
> >
> > That's a deliberately pathological example (and you can already write
> > something similarly misleading using the "for x in [12]" trick), but the
> > fact remains that we allow out of order evaluation in expressions in a
> way
> > that we don't permit for statements.
>
> OK. That's my concern as well. But my conclusion is different - I view
> this as a pretty strong argument that the complexity cost is too high
> to justify the feature, rather than as a difficulty we need to
> mitigate in order to make the feature usable.
>
> > With a syntactic marker though, there's typically going to be less
> ambiguity
> > about where a name comes from:
> >
> > x = 10
> > data = [.x*.x for i in range(10) if (12 as .x)]
> >
> > It's not a panacea (since you may still be shadowing a name from an outer
> > statement), and adapting it for PEP 3150 isn't without it's problems
> > (specifically, you need to allow ".x = 12" in the given clause to make
> the
> > names match up), but it should be less confusing than allowing a new
> > subexpression to interfere with name resolution semantics folks have been
> > relying on for years.
>
> On my screen right now, I can barely see the dots. That's in email
> with a proportional font, so not "real coding", but it's surprising
> (and somewhat depressing :-() to think that probably the majority of
> code I read these days is in emails.
>
> So I don't think that this is a good enough fix to warrant making
> Tim's screen look gritty.
>
> > If statement locals behave just like function locals, then there's no
> reason
> > to add them to the language in the first place - "(expr as name)" would
> just
> > become a confusing second way to spell "name = expr".
>
> Well, the whole reason this debate keeps coming up is because people
> keep finding places they want to type "name = expr" but they can't,
> because their context isn't a statement. We're basically trying to
> design a replacement for "name = expr" that can be used in an
> expression. And 

Re: [Python-ideas] PEP 572: Statement-Local Name Bindings

2018-03-02 Thread Nick Coghlan
On 2 March 2018 at 23:26, Paul Moore  wrote:

> Adding "mustn't just be another way to spell name = expr" to the
> requirements is an extra requirement - and arguably one that
> contradicts the original requirement which was "find a way to allow
> name = expr in expressions".
>

I consider allowing the semantic equivalent of "name = expr" as part of
arbitrary expressions to be an anti-requirement, not a requirement, for
three reasons:

1. It means that arbitrary statements may accidentally clobber local
variables that we care about. We used to have this for comprehension
iteration variables, and it was so widely deplored that we broke
compatibility with the variable overwriting behaviour in Python 3.0.

2. It means that naming a subexpression may significantly increase the
longevity of that reference (especially in generators and coroutines).

3. It means that naming a subexpression will define a new class or module
attribute when used in a class or module scope

Folks do sometimes *ask* for these semantics, as it's the most obvious
behaviour to ask for when it comes to naming subexpressions, but it would
be a really bad idea to say "yes" to those requests.

Chris's PEP addresses all those potential problems:

1. Statement locals explicitly avoid overwriting regular function locals
(although they may shadow them in the current PEP - the '.name' syntax
avoids even that)
2. Statement local bindings are cleared after each statement, so they only
significantly extend the reference lifespan when used in compound statement
headers or directly in the same statement as a yield or await. Even in
comprehensions they'll typically be cleared on the next loop iteration.
3. Statement locals aren't added to locals() or globals(), so they never
show up as module or class attributes either

The eventual conclusion may still be "The proposal adds too much additional
complexity without an adequate corresponding gain in expressiveness", but
that complexity does have a solid rationale behind it. (Although it may be
worth explicitly answering "Why not use the exact same semantics as 'name =
expr'? in the PEP itself, since it's a reasonable question to ask)

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572: Statement-Local Name Bindings

2018-03-02 Thread Paul Moore
On 2 March 2018 at 12:48, Nick Coghlan  wrote:
> The design intent related rationale stems from the fact that closed over
> references can live for an arbitrarily long time (as can regular function
> locals in a generator or coroutine), and I think statement locals should be
> as reliably ephemeral as we can reasonably make them if they're going to be
> different enough from function locals to be worth the hassle of adding them.
>
> So that means asking a bunch of questions and deliberately giving the
> *opposite* answer for statement locals than I would for function locals:
>
> * Visible in locals()? Yes for function locals, no for statement locals
> * Visible in frame.f_locals? Yes for function locals, no for statement
> locals
> * Prevents access to the same name in outer scopes? Yes for function locals,
> no for statement locals
> * Can be closed over? Yes for function locals, no for statement locals
>
> Answer "no" to all those questions is only reasonable if statement local
> references *look* different from regular variable names. But I also think we
> need to proposing answering "No" to all of them to make statement locals
> potentially interesting enough to be worth considering.

OK, that argument makes sense to me. At least in the sense that it
makes a good case for how statement-local names should work *if* we
adopt them. I reserve the right to change my mind, as I haven't
thought this through fully, but at least superficially I'm with you
this far.

I will note that I don't see this as a compelling reason for *having*
them, just a good analysis of how they might behave if we do.

> Neither PEP 527 nor 3150 *needs* the syntactic markers - the compiler can
> figure out what is going on because it does the symbol table analysis pass
> before the code generation pass, and hence can tag names appropriately based
> on what it finds.
>
> My concern is for people reading the code, where omitting a syntactic marker
> also forces *humans* to read things in two passes to make sure they
> understand them correctly. Consider this example:
>
> x = 10
> data = [x*x for i in range(10)]
>
> This will give you a 10 item list, where each item is 100.
>
> But now consider a world with statement locals, where statement locals use
> the same reference syntax as regular locals:
>
> x = 10
> data = [x*x for i in range(10) if (12 as x)]
>
> That's a deliberately pathological example (and you can already write
> something similarly misleading using the "for x in [12]" trick), but the
> fact remains that we allow out of order evaluation in expressions in a way
> that we don't permit for statements.

OK. That's my concern as well. But my conclusion is different - I view
this as a pretty strong argument that the complexity cost is too high
to justify the feature, rather than as a difficulty we need to
mitigate in order to make the feature usable.

> With a syntactic marker though, there's typically going to be less ambiguity
> about where a name comes from:
>
> x = 10
> data = [.x*.x for i in range(10) if (12 as .x)]
>
> It's not a panacea (since you may still be shadowing a name from an outer
> statement), and adapting it for PEP 3150 isn't without it's problems
> (specifically, you need to allow ".x = 12" in the given clause to make the
> names match up), but it should be less confusing than allowing a new
> subexpression to interfere with name resolution semantics folks have been
> relying on for years.

On my screen right now, I can barely see the dots. That's in email
with a proportional font, so not "real coding", but it's surprising
(and somewhat depressing :-() to think that probably the majority of
code I read these days is in emails.

So I don't think that this is a good enough fix to warrant making
Tim's screen look gritty.

> If statement locals behave just like function locals, then there's no reason
> to add them to the language in the first place - "(expr as name)" would just
> become a confusing second way to spell "name = expr".

Well, the whole reason this debate keeps coming up is because people
keep finding places they want to type "name = expr" but they can't,
because their context isn't a statement. We're basically trying to
design a replacement for "name = expr" that can be used in an
expression. And the status quo is "refactor your expression into
multiple statements". Doing so isn't always ideal (and particularly
grates on people coming from languages where assignments are
expressions, like C/C++) but it is always possible.

Adding "mustn't just be another way to spell name = expr" to the
requirements is an extra requirement - and arguably one that
contradicts the original requirement which was "find a way to allow
name = expr in expressions".

Designing a broader feature which solves the original problem is a
good goal, but we need to take care not to introduce scope creep or
over generalisation. In this case, IMO, we're not doing that (yet!)
but we are 

Re: [Python-ideas] PEP 572: Statement-Local Name Bindings

2018-03-02 Thread Nick Coghlan
On 2 March 2018 at 21:50, Paul Moore  wrote:

> On 2 March 2018 at 11:15, Nick Coghlan  wrote:
> > On 2 March 2018 at 19:05, Paul Moore  wrote:
> >>
> >> The problem with statement local variables is that the extent over
> >> which the name is in scope is not as clear to the human reader (the
> >> rules the *compiler* follows may be precise, but they aren't obvious
> >> to the human reader - that's the root of the debate I'm having with
> >> Chris over "what the reference implementation does isn't a sufficient
> >> spec"). In particular, assignment statements are non-obvious, as shown
> >> by the examples that triggered your suggestion of a "." prefix.
> >
> > Those examples didn't trigger the suggestion: the suggestion was borne
> from
> > the fact that I don't think it should be possible to close over statement
> > locals.
>
> Ah, OK. If closing over statement locals isn't allowed, then yes, they
> are a different type of name, and you may need to distinguish them. On
> the other hand, I'm not sure I agree with you that it shouldn't be
> possible to close over statement locals. I can see that there are a
> lot of *difficulties* with allowing it, but that's not the same.
>


> What's your logic for saying you shouldn't be able to close over a
> statement local name? What is fundamentally different about them that
> makes them unsuitable to work like all other names in Python?
>

I have two reasons, one based on design intent, one based on practicality
of implementation.

Starting with the practical motivation first: based on my experience
preventing the implementation variable from leaking in comprehensions, I
don't think it's going to be practical to allow closing over statement
locals while still scoping them to the statement that sets them in any
meaningful way. The difficulty of implementing that correctly is why I
ended up going for the implicit-nested-scope implementation for Python 3
comprehensions in the first place.

While I do assume it would technically be possible to go that way (it's
only software after all), it would require some *significant* changes to
the way at least CPython's compiler handles symbol analysis, and likely to
the way symtable analysis is handled in other compilers as well. By
contrast, if you drop the "must support closures" requirement, then the
required name mangling to only nested statements to re-use the same
statement local names without interfering with each other or with matching
function local names gets *much* simpler (especially with a syntactic
marker to distinguish statement local references from normal variable
names), since all you need to track is how many levels deep you are in
statement nesting within the current compilation unit.

The design intent related rationale stems from the fact that closed over
references can live for an arbitrarily long time (as can regular function
locals in a generator or coroutine), and I think statement locals should be
as reliably ephemeral as we can reasonably make them if they're going to be
different enough from function locals to be worth the hassle of adding them.

So that means asking a bunch of questions and deliberately giving the
*opposite* answer for statement locals than I would for function locals:

* Visible in locals()? Yes for function locals, no for statement locals
* Visible in frame.f_locals? Yes for function locals, no for statement
locals
* Prevents access to the same name in outer scopes? Yes for function
locals, no for statement locals
* Can be closed over? Yes for function locals, no for statement locals

Answer "no" to all those questions is only reasonable if statement local
references *look* different from regular variable names. But I also think
we need to proposing answering "No" to all of them to make statement locals
potentially interesting enough to be worth considering.

(Debuggers would need to access these in order to display them, so they'd
have to be available on the frame object together with metadata on the code
object to correctly populate them at runtime, but that's a solvable problem)

While this would require non-trivial compiler changes as well, they'd be
much safer updates with a lower risk of unintended consequences, since they
wouldn't need to touch the existing name resolution code - they'd be their
own thing, operating in parallel with the established dynamic name lookup
support.



> > PEP 3150 ended up needing syntactic markers as well, to handle the
> forward
> > references to names set in the `given` clause while staying within the
> LL(1)
> > parsing design constraint imposed on Python's grammar.
>
> Is this basically about forward references then? Certainly the "a = (1
> as a)" examples are a problem because of forward references. And the
> problem here is that we can't use the normal solution of simply
> prohibiting forward references ("Name assigned before declaration"
> errors) because - well, I'm not quite 

Re: [Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Paul Moore
On 2 March 2018 at 11:43, Chris Angelico  wrote:
> After dozens of posts and a wide variety of useful opinions and
> concerns being raised, here is the newest version of PEP 572 for your
> debating pleasure.

This is a distinct improvement - thanks for incorporating the varied
feedback so well.

I still remain -1, though. Reasons scattered through the other thread
but mostly relating to the fact that there are subtle differences
between statement-local names and other names in Python (notably that
you can't close over them). I don't think the benefits of the proposal
are sufficient to justify introducing a new
similar-but-subtly-different type of name.

Paul
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572: Statement-Local Name Bindings

2018-03-02 Thread Paul Moore
On 2 March 2018 at 11:15, Nick Coghlan  wrote:
> On 2 March 2018 at 19:05, Paul Moore  wrote:
>>
>> The problem with statement local variables is that the extent over
>> which the name is in scope is not as clear to the human reader (the
>> rules the *compiler* follows may be precise, but they aren't obvious
>> to the human reader - that's the root of the debate I'm having with
>> Chris over "what the reference implementation does isn't a sufficient
>> spec"). In particular, assignment statements are non-obvious, as shown
>> by the examples that triggered your suggestion of a "." prefix.
>
> Those examples didn't trigger the suggestion: the suggestion was borne from
> the fact that I don't think it should be possible to close over statement
> locals.

Ah, OK. If closing over statement locals isn't allowed, then yes, they
are a different type of name, and you may need to distinguish them. On
the other hand, I'm not sure I agree with you that it shouldn't be
possible to close over statement locals. I can see that there are a
lot of *difficulties* with allowing it, but that's not the same.
What's your logic for saying you shouldn't be able to close over a
statement local name? What is fundamentally different about them that
makes them unsuitable to work like all other names in Python?

> PEP 3150 ended up needing syntactic markers as well, to handle the forward
> references to names set in the `given` clause while staying within the LL(1)
> parsing design constraint imposed on Python's grammar.

Is this basically about forward references then? Certainly the "a = (1
as a)" examples are a problem because of forward references. And the
problem here is that we can't use the normal solution of simply
prohibiting forward references ("Name assigned before declaration"
errors) because - well, I'm not quite sure why, actually. Surely if
you're naming a subexpression that's repeated, you can always just
choose to name the *first* occurrence and use that name for the rest?
I guess the exception is statements that introduce or bind names
(assignments, for, etc). I'd still be inclined to just say prohibit
such cases (if we can't, then we're back into the territory of
implementation difficulties driving the design).

This all still feels to me like an attempt to rescue the proposal from
the issues that arise from not treating statement-local names exactly
like any other name.

> Right, but that extra notation *does* convey useful information to a reader
> that better enables local reasoning about a piece of code. Currently, if
> you're looking at an unfamiliar function and see a name you don't recognise,
> then you need to search the whole module for that name to see whether or not
> it's defined anywhere. Even if it's missing, you may still need to check for
> dynamic injection of module level names via globals().

Hang on, that's how all existing names in Python work (and in pretty
much any language that doesn't require explicit declarations). Surely
no-one is trying to suggest that this is a fundamental flaw?

> Seeing ".name" would be different (both for the compiler and for the human
> reader): if such a reference can't be resolved explicitly within the scope
> of the current statement, then *it's a bug* (and the compiler would be able
> to flag it as such at compile time).

Sorry, but you could use exactly that argument to propose that
function local variables should be prefixed with "$". I don't buy it.

I guess I remain -1 on the proposal, and nothing that's getting said
about how we can make it work is doing anything to persuade me
otherwise (quite the opposite).

Paul
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

2018-03-02 Thread Chris Angelico
After dozens of posts and a wide variety of useful opinions and
concerns being raised, here is the newest version of PEP 572 for your
debating pleasure.

Formatted version:

https://www.python.org/dev/peps/pep-0572/

There are now several more examples, greater clarity in edge cases,
and improved wording of the actual proposal and specifications. Also,
the reference implementation has been significantly enhanced, for
those who wish to try this themselves.

ChrisA

PEP: 572
Title: Syntax for Statement-Local Name Bindings
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


Abstract


Programming is all about reusing code rather than duplicating it.  When
an expression needs to be used twice in quick succession but never again,
it is convenient to assign it to a temporary name with small scope.
By permitting name bindings to exist within a single statement only, we
make this both convenient and safe against name collisions.


Rationale
=

When a subexpression is used multiple times in a list comprehension, there
are currently several ways to spell this, none of which is universally
accepted as ideal. A statement-local name allows any subexpression to be
temporarily captured and then used multiple times.

Additionally, this syntax can in places be used to remove the need to write an
infinite loop with a ``break`` in it.  Capturing part of a ``while`` loop's
condition can improve the clarity of the loop header while still making the
actual value available within the loop body.


Syntax and semantics


In any context where arbitrary Python expressions can be used, a named
expression can appear. This must be parenthesized for clarity, and is of
the form ``(expr as NAME)`` where ``expr`` is any valid Python expression,
and ``NAME`` is a simple name.

The value of such a named expression is the same as the incorporated
expression, with the additional side-effect that NAME is bound to that
value in all retrievals for the remainder of the current statement.

Just as function-local names shadow global names for the scope of the
function, statement-local names shadow other names for that statement.
They can also shadow each other, though actually doing this should be
strongly discouraged in style guides.

Assignment to statement-local names is ONLY through this syntax. Regular
assignment to the same name will remove the statement-local name and
affect the name in the surrounding scope (function, class, or module).

Statement-local names never appear in locals() or globals(), and cannot be
closed over by nested functions.


Execution order and its consequences


Since the statement-local name binding lasts from its point of execution
to the end of the current statement, this can potentially cause confusion
when the actual order of execution does not match the programmer's
expectations. Some examples::

# A simple statement ends at the newline or semicolon.
a = (1 as y)
print(y) # NameError

# The assignment ignores the SLNB - this adds one to 'a'
a = (a + 1 as a)

# Compound statements usually enclose everything...
if (re.match(...) as m):
print(m.groups(0))
print(m) # NameError

# ... except when function bodies are involved...
if (input("> ") as cmd):
def run_cmd():
print("Running command", cmd) # NameError

# ... but function *headers* are executed immediately
if (input("> ") as cmd):
def run_cmd(cmd=cmd): # Capture the value in the default arg
print("Running command", cmd) # Works

Some of these examples should be considered *bad code* and rejected by code
review and/or linters; they are not, however, illegal.


Example usage
=

These list comprehensions are all approximately equivalent::

# Calling the function twice
stuff = [[f(x), x/f(x)] for x in range(5)]

# External helper function
def pair(x, value): return [value, x/value]
stuff = [pair(x, f(x)) for x in range(5)]

# Inline helper function
stuff = [(lambda y: [y,x/y])(f(x)) for x in range(5)]

# Extra 'for' loop - see also Serhiy's optimization
stuff = [[y, x/y] for x in range(5) for y in [f(x)]]

# Iterating over a genexp
stuff = [[y, x/y] for x, y in ((x, f(x)) for x in range(5))]

# Expanding the comprehension into a loop
stuff = []
for x in range(5):
y = f(x)
stuff.append([y, x/y])

# Wrapping the loop in a generator function
def g():
for x in range(5):
y = f(x)
yield [y, x/y]
stuff = list(g)

# Using a statement-local name
stuff = [[(f(x) as y), x/y] for x in range(5)]

If calling ``f(x)`` is expensive or has side effects, the clean operation of
the list comprehension gets muddled. Using a short-duration name binding

Re: [Python-ideas] PEP 572: Statement-Local Name Bindings

2018-03-02 Thread Nick Coghlan
On 2 March 2018 at 19:05, Paul Moore  wrote:

> The problem with statement local variables is that the extent over
> which the name is in scope is not as clear to the human reader (the
> rules the *compiler* follows may be precise, but they aren't obvious
> to the human reader - that's the root of the debate I'm having with
> Chris over "what the reference implementation does isn't a sufficient
> spec"). In particular, assignment statements are non-obvious, as shown
> by the examples that triggered your suggestion of a "." prefix.
>

Those examples didn't trigger the suggestion: the suggestion was borne from
the fact that I don't think it should be possible to close over statement
locals.

If you can't close over statement locals, then it isn't acceptable to allow
this scenario:

x = 12
if (True as x):
def f():
return x
print(x, f()) # "True True"? Or "True 12"?
print(x, f()) # "12 12", but it's not obvious why it isn't "True True"

By contrast, if the two kinds of local namespace are visibly different,
then the nested scope *can't* give the appearance of referencing the
statement local:

x = 12
if (True as .x):
def f():
return x
print(.x, x, f()) # Clearly "True, 12, 12", since x never gets
rebound
print(x, f()) # Clearly "12, 12", since x never gets rebound


>
> [...]
>
> > Adding statement local variables into that mix *without* some form of
> > syntactic marker would mean taking an already complicated system, and
> making
> > it even harder to reason about correctly (especially if statement locals
> > interact with nested scopes differently from the way other locals in the
> > same scope do).
>
> Well, an alternative to a syntactic marker would be an
> easy-to-determine extent. That's where proposals like PEP 3150 (the
> "given" clause) work better, because they provide a clearer indication
> of the extent of the new scope. IMO, lack of a well-defined extent is
> a flaw of this proposal, and syntactic markers are essentially a
> (ugly) workaround for that flaw.
>

PEP 3150 ended up needing syntactic markers as well, to handle the forward
references to names set in the `given` clause while staying within the
LL(1) parsing design constraint imposed on Python's grammar.

Currently it proposes `?.name` as that marker, with `?` referring to the
entire given namespace, but it could equally well use `.name` instead (and
if you wanted a reference to a namespace instead, you'd need to define one
inside the given clause).

One of the key *problems* with PEP 3150 though is that it doesn't compose
nicely with other compound statements, whereas PEP 572 does (by treating
each statement as its own extent - PEP 3150 then just provides a way to add
a suite to statements that don't already have one of their own).


> > Thus the intent behind the ".NAME" suggestion is to ask whether or not
> it's
> > possible to allow for name bindings that are strictly local to a
> compilation
> > unit (i.e. without allowing dynamic runtime access to outer scopes or
> from
> > contained scopes), *without* incurring the cost of making ordinary NAME
> > references even more complicated to understand.
>
> ... or the cost of imposing a more user-visible indication of the
> extent of the scope into the proposal.
>

Right, but that extra notation *does* convey useful information to a reader
that better enables local reasoning about a piece of code. Currently, if
you're looking at an unfamiliar function and see a name you don't
recognise, then you need to search the whole module for that name to see
whether or not it's defined anywhere. Even if it's missing, you may still
need to check for dynamic injection of module level names via globals().

Seeing ".name" would be different (both for the compiler and for the human
reader): if such a reference can't be resolved explicitly within the scope
of the current statement, then *it's a bug* (and the compiler would be able
to flag it as such at compile time).

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572: Statement-Local Name Bindings

2018-03-02 Thread Nick Coghlan
On 2 March 2018 at 16:39, Ethan Furman  wrote:

> On 03/01/2018 09:08 PM, Nick Coghlan wrote:
>
>> Adding statement local variables into that mix *without* some form of
>> syntactic marker would mean taking an already
>> complicated system, and making it even harder to reason about correctly
>> (especially if statement locals interact with
>> nested scopes differently from the way other locals in the same scope do).
>>
>
> Seems like it would far easier and (IMHO) more useful to scale the
> proposal back from a statement scope to simple expression assignment, and
> the variable is whatever scope it would have been if assigned to outside
> the expression (default being local, but non-local or global if already
> declared as such).
>

Because that would put us back in the exact same problematic situation we
had when "[x*x for x in sequence]" leaked the iteration variable (only
worse): no function locals would be safe, since arbitrary expressions could
clobber them, not just name binding operations (assignment, import
statements, for loops, with statements, exception handlers, class and
function definitions).


> No grammatical grit on anyone's monitor, no confusion about which variable
> is being accessed, and no confusion about the lifetime of that variable
> (okay, no /extra/ confusion ;) .
>

Unfortunately, it would mean a lot more "All I did was name a repeated
subexpression and now my function is behaving weirdly".


> Maybe somebody could explain why a statement-local limited scope variable
> is better than an ordinary well-understood local-scope variable?
> Particularly why it's better enough to justify more line-noise in the
> syntax.  I'm willing to be convinced (not happy to, just willing ;) .
>

It breaks the expectation that only a well defined subset of statement can
make changes to local name bindings.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 572: Statement-Local Name Bindings

2018-03-02 Thread Paul Moore
On 2 March 2018 at 05:08, Nick Coghlan  wrote:
> On 1 March 2018 at 19:30, Paul Moore  wrote:
>>
>> Agreed. This feels far to much like Perl's "sigils" that attach to a
>> name ($var is a scalar, @var is a list, etc). Strong -1 from me.
>
> While that's a fair criticism, one of the current challenges with Python's
> variable naming is that given a NAME reference, there are already several
> potential places for that name to be resolved:
>
> * the current local scope
> * an enclosing function scope
> * the module globals
> * the builtin namespace

While that is true, the current scenario is (conceptually, at least) a
relatively traditional set of 4 nested namespaces, with name
resolution working from innermost to outermost, and with the extent of
the scopes being pretty clearly defined. So although the *compiler*
may have to defer a chunk of that resolution to runtime, the human
reader can work with a relatively conventional model and not hit
problems in the majority of cases.

The problem with statement local variables is that the extent over
which the name is in scope is not as clear to the human reader (the
rules the *compiler* follows may be precise, but they aren't obvious
to the human reader - that's the root of the debate I'm having with
Chris over "what the reference implementation does isn't a sufficient
spec"). In particular, assignment statements are non-obvious, as shown
by the examples that triggered your suggestion of a "." prefix.

[...]

> Adding statement local variables into that mix *without* some form of
> syntactic marker would mean taking an already complicated system, and making
> it even harder to reason about correctly (especially if statement locals
> interact with nested scopes differently from the way other locals in the
> same scope do).

Well, an alternative to a syntactic marker would be an
easy-to-determine extent. That's where proposals like PEP 3150 (the
"given" clause) work better, because they provide a clearer indication
of the extent of the new scope. IMO, lack of a well-defined extent is
a flaw of this proposal, and syntactic markers are essentially a
(ugly) workaround for that flaw.

> Thus the intent behind the ".NAME" suggestion is to ask whether or not it's
> possible to allow for name bindings that are strictly local to a compilation
> unit (i.e. without allowing dynamic runtime access to outer scopes or from
> contained scopes), *without* incurring the cost of making ordinary NAME
> references even more complicated to understand.

... or the cost of imposing a more user-visible indication of the
extent of the scope into the proposal.

Paul
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/