Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Greg Ewing

Nick Coghlan wrote:

I'd be +0 on an "is=" spelling


But "is=' looks like some kind of comparison
operator. This seems even more conusing to me.

--
Greg

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread MRAB

On 2018-04-24 23:32, Cameron Simpson wrote:

On 24Apr2018 08:51, Ethan Furman  wrote:

When I compare to variables from outer scopes they *usually* are on
the *right* side of '=='.


You mean something like

 if 2 == x:

?  I never write code like that, and I haven't seen it, either.


Just to this, I also never write code like that but I've certainly seen it
advocated.

I think the rationale was that it places the comparison value foremost in one's
mind, versus the name being tested. I'm not persuaded, but it is another
subjective situation.

It's sometimes advocated in C/C++ code to help catch the inadvertent use 
of = instead of ==, but that's not a problem in Python.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Cameron Simpson

On 24Apr2018 08:51, Ethan Furman  wrote:

When I compare to variables from outer scopes they *usually* are on
the *right* side of '=='.


You mean something like

 if 2 == x:

?  I never write code like that, and I haven't seen it, either.


Just to this, I also never write code like that but I've certainly seen it 
advocated.


I think the rationale was that it places the comparison value foremost in one's 
mind, versus the name being tested. I'm not persuaded, but it is another 
subjective situation.


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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Steven D'Aprano
On Tue, Apr 24, 2018 at 10:29:11PM +0100, Anthony Flury via Python-Dev wrote:

> If Python is going to do assignment expressions we shouldn't overload 
> parens in my opinion - we should have a separate operator - doing this 
> avoids needing to exclude rebinding, and makes such expressions 
> considerably more useful.

Exactly!

Yury's suggestion to prohibit rebinding existing names is throwing away 
the baby with the bathwater. Using assignment-expression to over-write 
an existing variable is only a error when it is a mistake, done by 
accident.

To satisfy the compiler, we have to invent new and unique names for what 
is conceptually the same variable being reused. Instead of simplifying 
your code, it will make it more complex.

Despite his statement that there's only one assignment, there are 
actually two: assignment that allows rebinding, and assignment that 
sometimes doesn't. The semantic differences between Yury's = and = are 
actually *greater* than the differences between = and :=


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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Chris Angelico
On Wed, Apr 25, 2018 at 7:29 AM, Anthony Flury via Python-Dev
 wrote:
> On 24/04/18 17:11, Yury Selivanov wrote:
>>
>> On Tue, Apr 24, 2018 at 12:03 PM, Ethan Furman  wrote:
>> [..]
>>>
>>> But I do write this:
>>>
>>>def wrapper(func, some_value):
>>>  value_I_want = process(some_value)
>>>  def wrapped(*args, **kwds):
>>>if value_I_want == 42:
>>>   ...
>>
>> But this pattern is more rare than comparing local variables. That's
>> the point I'm trying to use.  Besides, to make it an assignment
>> expression under my proposal you would need to use parens. Which makes
>> it even less likely that you confuse '=' and '=='.
>
>
> Just because you wrap a set of character in parens doesn't mean that you
> wont potentially mistype what you should type inside the parens. The failure
> mode of in C :
>
> if (a = 3)
> do_something_with_a(a);
>
> Is Incredibly common even with very experienced developers - so much so that
> most linters flag it as a likely error, and I think gcc has an option to
> flag it as a warning - even though it is valid and very occasionally it is
> useful.

Technically what you have there trips *two* dodgy conditions, and
could produce either warning or both:

1) Potential assignment where you meant comparison
2) Condition is always true.

The combination makes it extremely likely that this wasn't intended.
It's more dangerous, though, when the RHS is a function call...

> Also many developers who come to Python from languages such as C will still
> place parens around conditionals - this means that a typo which will cause a
> Syntax Error in current versions, but would cause a potentially subtle bug
> under your implementation (unless you maintain the rule that you can't
> rebind currently bound names - which renders the whole idea useless in loops
> (as already discussed at length).

Yuri, look how many of the python-dev readers have completely
misinterpreted this "can't rebind" rule. I think that's a fairly clear
indication that the rule is not going to be well understood by anyone
who isn't extremely familiar with the way the language is parsed. I
hesitate to say outright that it is a *bad rule*, but that's the lines
I'm thinking along.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Anthony Flury via Python-Dev

On 24/04/18 17:11, Yury Selivanov wrote:

On Tue, Apr 24, 2018 at 12:03 PM, Ethan Furman  wrote:
[..]

But I do write this:

   def wrapper(func, some_value):
 value_I_want = process(some_value)
 def wrapped(*args, **kwds):
   if value_I_want == 42:
  ...

But this pattern is more rare than comparing local variables. That's
the point I'm trying to use.  Besides, to make it an assignment
expression under my proposal you would need to use parens. Which makes
it even less likely that you confuse '=' and '=='.


Just because you wrap a set of character in parens doesn't mean that you 
wont potentially mistype what you should type inside the parens. The 
failure mode of in C :


    if (a = 3)
        do_something_with_a(a);

Is Incredibly common even with very experienced developers - so much so 
that most linters flag it as a likely error, and I think gcc has an 
option to flag it as a warning - even though it is valid and very 
occasionally it is useful.


Also many developers who come to Python from languages such as C will 
still place parens around conditionals - this means that a typo which 
will cause a Syntax Error in current versions, but would cause a 
potentially subtle bug under your implementation (unless you maintain 
the rule that you can't rebind currently bound names - which renders the 
whole idea useless in loops (as already discussed at length).


I also still can't think of a single other Python construct where the 
semantics of an operator are explicitly modified by syntaxtic elements 
outside the operator. For mathematical operators, the surrounding parens 
modifies the grouping of the operators but not the semantics (* means *, 
it is just the operands which potentially change).


You could argue that your proposal overloads the semantics of the parens 
(similar to how braces are overloaded to implement dictionaries and set 
literals), but I don't think that overloading the semantics of parens is 
good idea.


If Python is going to do assignment expressions we shouldn't overload 
parens in my opinion - we should have a separate operator - doing this 
avoids needing to exclude rebinding, and makes such expressions 
considerably more useful.


--
Anthony Flury
email : *anthony.fl...@btinternet.com*
Twitter : *@TonyFlury *

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Barry Warsaw
On Apr 24, 2018, at 06:55, Antoine Pitrou  wrote:
> 
> If the ambition is to find a piece of syntax that reads as "binds",
> then we can use a variation on the FLUFL operator: "<->".

FLUFL Override Approved!

-Barry



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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Chris Angelico
On Wed, Apr 25, 2018 at 2:57 AM, Steven D'Aprano  wrote:
> On Wed, Apr 25, 2018 at 02:42:08AM +1000, Chris Angelico wrote:
>
>> > from math import *
>> > process(arg, (pi = 1), pi+1)  # allowed
>
>
>> That's not allowed at local scope (at least, it's not allowed at
>> function scope - is there any other "local scope" at which it is
>> allowed?).
>
> Of course: local just means the current scope, wherever you happen to
> be. Inside a function, local is the current function scope. Inside a
> class body, local is the class body scope. At the top level of the
> module, local means the module scope (and locals() returns the same dict
> as globals()).
>
> If Yury means for this "cannot mask existing variables" to only operate
> inside functions, that means that you can mask existing variables if you
> use assignment expressions in class bodies or top-level module code.

I don't have a quote for it, but I was under the impression that this
shielding was indeed function-scope-only.

Actually, now that I think about it, I'm not sure whether Yuri's plan
for assignment expressions even included module scope.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Steven D'Aprano
On Wed, Apr 25, 2018 at 02:42:08AM +1000, Chris Angelico wrote:

> > from math import *
> > process(arg, (pi = 1), pi+1)  # allowed

 
> That's not allowed at local scope (at least, it's not allowed at
> function scope - is there any other "local scope" at which it is
> allowed?).

Of course: local just means the current scope, wherever you happen to 
be. Inside a function, local is the current function scope. Inside a 
class body, local is the class body scope. At the top level of the 
module, local means the module scope (and locals() returns the same dict 
as globals()).

If Yury means for this "cannot mask existing variables" to only operate 
inside functions, that means that you can mask existing variables if you 
use assignment expressions in class bodies or top-level module code.


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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Chris Angelico
On Wed, Apr 25, 2018 at 2:23 AM, Steven D'Aprano  wrote:
> On Tue, Apr 24, 2018 at 11:25:58AM -0400, Yury Selivanov wrote:
>
>> No, it doesn't. The check is performed during compile phase, and
>> Python does not unroll loops. Anyways, read below.
>
> What does unrolling loops have to do with anything? And besides, loop
> unrolling is an implementation detail -- maybe Python will unroll loops,
> maybe it won't.
>
> If you insist that the check is only done at compile time, then your
> description is wrong and your rule that "it is *not* allowed to mask
> names in the current local scope" is false. It *is* allowed to shadow
> names in the local scope, but only names that cannot be determined at
> compile-time.
>
> from math import *
> process(arg, (pi = 1), pi+1)  # allowed
>
> That's more and worse complexity.

That's not allowed at local scope (at least, it's not allowed at
function scope - is there any other "local scope" at which it is
allowed?). Not sure if you can craft equivalent shenanigans with
'exec'.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Steven D'Aprano
On Tue, Apr 24, 2018 at 11:35:20AM -0400, Yury Selivanov wrote:

> Yes, it would force users to come up with better names *iff* they want
> to use this new sugar:
> 
>   if (first_target = get_first_candidate()) ...
>   elif (second_target = get_second_candidate()) ...

They're not better names. Adding "first_" and "second_" prefixes are 
just meaningless waffle added to the name "target" to satisfy the 
compiler so it doesn't complain about reusing the name.

And it is a clear inconsistency with = as a statement and = as an 
expression:

# allowed
target = get_first_candidate()
if target:
...
else:
target = get_second_candidate()
if target: ...


# refactor, and we get a syntax error
if (target = get_first_candidate()):
...
elif (target = get_second_candidate()):
...


And I cannot even begin to guess whether this will be allowed or not:

if (target = get_first_candidate()):
...
while (target = get_second_candidate()):
...


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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Chris Angelico
On Wed, Apr 25, 2018 at 2:28 AM, Steven D'Aprano  wrote:
> On Tue, Apr 24, 2018 at 10:58:24AM -0400, Yury Selivanov wrote:
>
>> Since 'diff' and 'g' must be new names according to rule (3), those
>> who read the code will notice that both were not previously bound.
>
> How am I supposed to notice that they've never been bound without
> carefully reading through the rest of the function in detail, checking
> every single expression and statement?
>
> And besides, you have already established that there are exceptions to
> the rule "names must be new names". For example, in loops.
>
> What other exceptions are there?
>

Yuri is talking about "new" in the syntactic sense. A new name is one
which, reading lexically through the code, has not yet been assigned
to in the function. (I don't know what happens with global/nonlocal
declarations.) Loops have a single point at which the name is assigned
to. This has a single point where the name is assigned, too, even
though you'll never hit it:

def f(x):
if x is not x:
y = 1
print(y) # UnboundLocalError

While I disagree with the proposal, it is at least sane from the
compiler's POV. I don't think it makes sense from a human's POV, but
it's internally consistent.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Steven D'Aprano
On Tue, Apr 24, 2018 at 11:25:58AM -0400, Yury Selivanov wrote:

> No, it doesn't. The check is performed during compile phase, and
> Python does not unroll loops. Anyways, read below.

What does unrolling loops have to do with anything? And besides, loop 
unrolling is an implementation detail -- maybe Python will unroll loops, 
maybe it won't.

If you insist that the check is only done at compile time, then your 
description is wrong and your rule that "it is *not* allowed to mask 
names in the current local scope" is false. It *is* allowed to shadow 
names in the local scope, but only names that cannot be determined at 
compile-time.

from math import *
process(arg, (pi = 1), pi+1)  # allowed

That's more and worse complexity.

And what about masking names in the class, nonlocal, global and 
builtin scopes? Even more complexity and inconsistent behaviour!

def function():
global a
a = b = 1
process(arg, (a = 2), a+1)  # allowed
process(arg, (b = 2), b+1)  # not allowed



> > I believe that one of the most important use-cases for binding-
> > expression syntax is while loops, like this modified example taken from
> > PEP 572 version 3:
> >
> > while (data = sock.read()):
> > print("Received data:", data)
> >
> > If you prohibit re-binding data, that prohibits cases like this, or even
> > using it inside a loop:
> >
> > for value in sequence:
> > process(arg, (item = expression), item+1)
> 
> No it doesn't. symtable in Python works differently. I encourage you
> to test my reference implementation:
> 
> py> for val in [1, 2, 3]:
> ...   print((item=val), item+1)
> ...
> 1 2
> 2 3
> 3 4

Then your description is false: the assignment in the second time around 
the loop is masking the value that was set the first time around the 
loop. I should be able to unroll the loop by hand, and the code should 
still work:


val = 1
print((item=val), item+1)
val = 2
print((item=val), item+1)
val = 3
print((item=val), item+1)


Does your reference implementation allow that? If not, then you have 
added yet another inconsistency and obscure rule to be learned: using 
assignment expressions will break loop unrolling even if you do it by 
hand.

If it *does* allow that, then so much for your claim that you cannot 
mask existing variables. It can.


> > Why is this allowed?
> >
> > x = 1  # both are statement forms
> > x = 2
> >
> > but this is prohibited?
> >
> > x = 1
> > (x = 2)  # no rebinding is allowed
> >
> > and even more confusing, this is allowed!
> >
> > (x = 1)  # x doesn't exist yet, so it is allowed
> > x = 2  # statement assignment is allowed to rebind
> 
> These all are very limited code snippets that you're unlikely to see
> in real code.

Oh come on now Yury, please be reasonable. They're only *sketches* of 
more realistic code. Of course I'm not actually going to write something 
like 

x = 1
(x = 2)

but do you really need me to take the time and effort to come up with a 
more realistic (and therefore complex) example? Okay.


# allowed
mo = re.match(HEADER_PATTERN, string)
if mo:
process_header(mo)
...  # much later
mo = re.match(FOOTER_PATTERN, string)
if mo:
   process_footer(no)



# not allowed
mo = re.match(HEADER_PATTERN, string)
if mo:
process_header(mo)
...  # much later
if (mo = re.match(FOOTER_PATTERN, string)):  # SyntaxError
   process_footer(no)



You stated that 'There are no "arcane and confusing rules" about "=", 
it's rather simple' but every time we look closely at it, the rules seem 
to get more arcane and confusing.

- why is it okay to mask nonlocal, global, class and builtin
  names, but not local?

- for module-level code, how is the compiler supposed to determine
  the local names in the face of wildcard imports?

- why is it a syntax error to assign to a name which is not
  actually used?

# not allowed
if "a".upper() == "XYZ"[-1].lower():
spam = "this is dead code and will never happen"
process(arg, (spam=expression), spam+1)  # syntax error

# but this is allowed
if "a".upper() == "XYZ"[-1].lower():
spam = "this is dead code and will never happen"
spam = expression
process(arg, spam, spam+1)


- why can you *sometimes* mask existing local variables, if
  they are used in a loop, but not *other* local variables?

- how does this stop *me*, the human reader, from misreading
  (name=expression) as an equality test?



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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Steven D'Aprano
On Tue, Apr 24, 2018 at 10:58:24AM -0400, Yury Selivanov wrote:

> Since 'diff' and 'g' must be new names according to rule (3), those
> who read the code will notice that both were not previously bound.

How am I supposed to notice that they've never been bound without 
carefully reading through the rest of the function in detail, checking 
every single expression and statement?

And besides, you have already established that there are exceptions to 
the rule "names must be new names". For example, in loops.

What other exceptions are there?


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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Yury Selivanov
On Tue, Apr 24, 2018 at 12:03 PM, Ethan Furman  wrote:
[..]
> But I do write this:
>
>   def wrapper(func, some_value):
> value_I_want = process(some_value)
> def wrapped(*args, **kwds):
>   if value_I_want == 42:
>  ...

But this pattern is more rare than comparing local variables. That's
the point I'm trying to use.  Besides, to make it an assignment
expression under my proposal you would need to use parens. Which makes
it even less likely that you confuse '=' and '=='.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Yury Selivanov
On Tue, Apr 24, 2018 at 11:58 AM, Chris Angelico  wrote:
> On Wed, Apr 25, 2018 at 1:49 AM, Yury Selivanov  
> wrote:
>> On Tue, Apr 24, 2018 at 11:34 AM, Steven D'Aprano  
>> wrote:
[..]
>>> There's no advantage to using binding-expressions unless you're going to
>>> re-use the name you just defined, and that re-use will give you a hint
>>> as to what is happening:
>>>
>>> my_func(arg, buffer=(buf := [None]*get_size()), size=len(buf))
>>
>> Again, this is very subjective, but this code would fail my code review :)
>>
>> Don't you find
>>
>>   buf = [None] * get_size()
>>   my_func(arg, buffer=buf, size=len(buf))
>>
>> to be more readable?
>
> Only if 'buf' is going to be used elsewhere. I'd be looking down below
> for some other use of 'buf'. Technically the same could be true of the
> inline assignment, but it makes more sense for a "this statement only"
> name binding to be within that statement, not broken out and placed
> above it as another operation at equal importance.

Well, you can use empty lines to visually indicate that 'buf' is
related to the call.

Moreover, 'buf' is still available to the code below that code and
sometimes be used there. You can't tell for sure until you glance over
the entire file/function. PEP 572 does not implement any sort of
sub-scoping.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Chris Angelico
On Wed, Apr 25, 2018 at 1:56 AM, Yury Selivanov  wrote:
> On Tue, Apr 24, 2018 at 11:51 AM, Ethan Furman  wrote:
>
>>> When I compare to variables from outer scopes they *usually* are on
>>> the *right* side of '=='.
>>
>>
>> You mean something like
>>
>>   if 2 == x:
>>
>> ?  I never write code like that, and I haven't seen it, either.
>
> Hm. I mean this:
>
>const = 'something'
>
>def foo(arg):
>  if arg == const:
> do something
>
> Note that "const" is on the right side of "==".
>
> Would you write this as
>
>def foo(arg):
>   if const == arg:
>
> ? ;)

That's assuming the global is a constant. What if it's a mode-setting marker?

def foo(arg):
...
if output == "verbose" or (output != "quiet" and error_count):
print("Arg foo'd", arg)
print("Errors found:", error_count)

Then I would definitely put the variable first. And I know a lot of
people who would parenthesize the first condition in this.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Ethan Furman

On 04/24/2018 08:56 AM, Yury Selivanov wrote:

On Tue, Apr 24, 2018 at 11:51 AM, Ethan Furman  wrote:


When I compare to variables from outer scopes they *usually* are on
the *right* side of '=='.



You mean something like

   if 2 == x:

?  I never write code like that, and I haven't seen it, either.


Hm. I mean this:

const = 'something'

def foo(arg):
  if arg == const:
 do something

Note that "const" is on the right side of "==".

Would you write this as

def foo(arg):
   if const == arg:

? ;)


Heh, no.

But I do write this:

  def wrapper(func, some_value):
value_I_want = process(some_value)
def wrapped(*args, **kwds):
  if value_I_want == 42:
 ...

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Chris Angelico
On Wed, Apr 25, 2018 at 1:49 AM, Yury Selivanov  wrote:
> On Tue, Apr 24, 2018 at 11:34 AM, Steven D'Aprano  wrote:
>> On Tue, Apr 24, 2018 at 11:05:57AM -0400, Yury Selivanov wrote:
>>
>>> Well, `my_func(a=(b:=foo))` or `my_func(b:=foo)` are also barely
>>> readable to my eye.
>>
>> There's no advantage to using binding-expressions unless you're going to
>> re-use the name you just defined, and that re-use will give you a hint
>> as to what is happening:
>>
>> my_func(arg, buffer=(buf := [None]*get_size()), size=len(buf))
>
> Again, this is very subjective, but this code would fail my code review :)
>
> Don't you find
>
>   buf = [None] * get_size()
>   my_func(arg, buffer=buf, size=len(buf))
>
> to be more readable?

Only if 'buf' is going to be used elsewhere. I'd be looking down below
for some other use of 'buf'. Technically the same could be true of the
inline assignment, but it makes more sense for a "this statement only"
name binding to be within that statement, not broken out and placed
above it as another operation at equal importance.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Yury Selivanov
On Tue, Apr 24, 2018 at 11:51 AM, Ethan Furman  wrote:

>> When I compare to variables from outer scopes they *usually* are on
>> the *right* side of '=='.
>
>
> You mean something like
>
>   if 2 == x:
>
> ?  I never write code like that, and I haven't seen it, either.

Hm. I mean this:

   const = 'something'

   def foo(arg):
 if arg == const:
do something

Note that "const" is on the right side of "==".

Would you write this as

   def foo(arg):
  if const == arg:

? ;)

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Nick Coghlan
On 25 April 2018 at 01:35, Yury Selivanov  wrote:
> On Tue, Apr 24, 2018 at 11:31 AM, Nick Coghlan  wrote:
>> I *do* think the "no name rebinding except in a while loop header"
>> restriction would be annoying for the if/elif use case and the while
>> use case:
>>
>> while (item = get_item()) is not first_delimiter:
>> # First processing loop
>> while (item = get_item()) is not second_delimiter:
>> # Second processing loop
>> # etc...
>>
>> if (target = get_first_candidate()) is not None:
>> ...
>> elif (target = get_second_candidate()) is not None:
>> ...
>> elif (target = get_third_candidate()) is not None:
>> ...
>
> Yes, it would force users to come up with better names *iff* they want
> to use this new sugar:
>
>   if (first_target = get_first_candidate()) ...
>   elif (second_target = get_second_candidate()) ...

Sorry, I didn't make the intended nature of that example clear:

if (target = get_first_candidate()) is not None:
... # Any setup code specific to this kind of target
elif (target = get_second_candidate()) is not None:
... # Any setup code specific to this kind of target
elif (target = get_third_candidate()) is not None:
... # Any setup code specific to this kind of target
else:
raise RuntimeError("No valid candidate found")
# Common code using target goes here

Using a separate name in each branch wouldn't solve the problem of
binding the *same* name for the common code to use later - you'd have
to put a "target = candidate_n" bit of boilerplate in each branch.

Cheers,
Nick.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Yury Selivanov
On Tue, Apr 24, 2018 at 11:34 AM, Steven D'Aprano  wrote:
> On Tue, Apr 24, 2018 at 11:05:57AM -0400, Yury Selivanov wrote:
>
>> Well, `my_func(a=(b:=foo))` or `my_func(b:=foo)` are also barely
>> readable to my eye.
>
> There's no advantage to using binding-expressions unless you're going to
> re-use the name you just defined, and that re-use will give you a hint
> as to what is happening:
>
> my_func(arg, buffer=(buf := [None]*get_size()), size=len(buf))

Again, this is very subjective, but this code would fail my code review :)

Don't you find

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

to be more readable?

IMHO this example is why we shouldn't implement any form of assignment
expressions in Python :)

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Ethan Furman

On 04/24/2018 08:35 AM, Yury Selivanov wrote:


Yes, it would force users to come up with better names *iff* they want
to use this new sugar:

   if (first_target = get_first_candidate()) ...
   elif (second_target = get_second_candidate()) ...


And then the common code below that only cares about a target being found now 
has to do a

  item = first_target or second_target or ...

I don't see that as an improvement.

--
~Ethan~

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Ethan Furman

On 04/24/2018 08:19 AM, Yury Selivanov wrote:


Yes, because I'm trying to think about this from a pragmatic side of
things. My question to myself: "what syntax could I use that would
prevent me from making '=' vs '==' mistake when I code?"  To me, the
answer is that I usually want to compare local variables.


I think we need to disambiguate between typo-typos and thinko-typos.  I suspect the vast majority of the '=' bugs are 
not due to the programmer /thinking/ the wrong operation, but of their hands/keyboards not /entering/ the right symbols; 
having a legal operator ("==") degrade into another legal operator ("=") that looks similar but means incredibly 
different things is a trap that we should not add to Python.


You might say that we have the same problems with ">=", "<=", and "!=".  We don't with "!=" because neither "!" nor "=" 
can stand alone and would fail.  We only have it partially with "<=" and ">=" because missing the angle bracket results 
in failure, but missing the "=" results in a working statement -- but that statement is still the same type of operation 
and is easier to debug when boundary cases fail.



When I compare to variables from outer scopes they *usually* are on
the *right* side of '=='.


You mean something like

  if 2 == x:

?  I never write code like that, and I haven't seen it, either.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Yury Selivanov
On Tue, Apr 24, 2018 at 11:28 AM, Chris Angelico  wrote:

> On re-thinking this, I think the distinction IS possible, but (a) only
> in function/class scope, not at global; and (b) would be defined in
> terms of lexical position, not run-time. For instance:
>
> def f():
> (a = 1) # Legal; 'a' has not been used yet
> a = 2 # doesn't change that
>
> def f(a):
> (a = 1) # Invalid - 'a' has been used already
>
> def f():
> while (a = get_next()): # Legal
> ...

Now *this* is a weird rule. Moving functions around files would become
impossible.

Please experiment with my reference implementation, it already
implements my proposal in full. Loops and inline assignments work as
expected in it.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Yury Selivanov
On Tue, Apr 24, 2018 at 11:27 AM, Steven D'Aprano  wrote:
> On Tue, Apr 24, 2018 at 11:03:35AM -0400, Yury Selivanov wrote:
>
>> My point was that when you see lots of '=' and ':=' used at the
>> statement level, one might try to write "if x = 1" instead of "if x :=
>> 1" -- boom, we have an unexpected SyntaxError for some users.
>
> That's a *good* thing. They will then learn not to write x = 1 as an
> expression.
>
> Also, if I write lots of x := 1 binding-expressions as statements, my
> code is bad and deserves to fail code-review. But why would I write the
> extra colon (one character, two key-presses) to use
>
> x := 1
>
> as a statement, when x = 1 will work? That's a sure sign that I don't
> know what I'm doing. (Or that I desperately wish I was writing Pascal.)

In JavaScript there's a new backticks syntax for string—their variant
of f-strings.  I'm seeing a lot of JS coders that use backticks
everywhere, regardless if there's formatting in them or not.  The
result is that some JS code in popular libraries has now *three*
different string literal syntaxes separated by one line of code. It
looks weird. I expect to see something similar in Python code if we
adapt ':='.  I don't think the language will benefit from this.

FWIW I'm fine with keeping the status quo and not adding new syntax at all.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Steven D'Aprano
On Tue, Apr 24, 2018 at 11:05:57AM -0400, Yury Selivanov wrote:

> Well, `my_func(a=(b:=foo))` or `my_func(b:=foo)` are also barely
> readable to my eye.

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

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


> My expectation is that users won't use any form
> of assignment expressions in function calls, it's painful with both
> proposals.

If binding-expressions are accepted into the language, I will certainly 
use them in function calls, *if and when appropriate*. I don't expect it 
will be common, but I'm sure it will happen.



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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Chris Angelico
On Wed, Apr 25, 2018 at 1:15 AM, Steven D'Aprano  wrote:
> By the way, the check for existing variables cannot help to be either
> incomplete or incorrect if you try to do it at compile time:
>
>
> from module import *
> (x = 2)  # allowed or not allowed?
>
>
> If you don't like wild-card imports, how about this:
>
> if random.random() > 0.5:
> spam = 1
> else:
> eggs = 1
> (spam = 2)  # allowed or not? no way to tell at compile time
>
>
> But doing the rebinding/shadowing check at runtime will slow down
> binding expressions, and lead to even more arcane and confusing results:
>
> it = iter("abc")
> while (obj = next(it)):
> print(obj)
>
>
> will print "a" on the first loop, but then raise an exception on
> the second time loop as obj now exists.

On re-thinking this, I think the distinction IS possible, but (a) only
in function/class scope, not at global; and (b) would be defined in
terms of lexical position, not run-time. For instance:

def f():
(a = 1) # Legal; 'a' has not been used yet
a = 2 # doesn't change that

def f(a):
(a = 1) # Invalid - 'a' has been used already

def f():
while (a = get_next()): # Legal
...

This could be handled in the symbol collection pass; if the name
already exists in the function's locals, it's disallowed. But I still
stand by my statement that this creates bizarre cases, and yes, I know
that that word is subjective (just like "readable", "intuitive", and
"sensible"). The rules as given sound like they would make great
linter rules and terrible syntax rules. They are closely aligned with
the OP's experience and usage patterns - which means that, as a
personal linter, they could marvellously assist in catching bugs. You
could have personal (or organization-wide) linter rules disallowing
"class foo:" with a lower-case name, and disallowing the rebinding of
any name in ALL_CAPS, but I would not want either rule codified into
language syntax.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Yury Selivanov
On Tue, Apr 24, 2018 at 11:31 AM, Nick Coghlan  wrote:
> On 25 April 2018 at 00:54, Eric Snow  wrote:
>> Regardless, your 3 rules would benefit either syntax.  Nick may have a
>> point that the rules might be an excessive burden, but I don't think
>> it's too big a deal since the restrictions are few (and align with the
>> most likely usage) and are limited to syntax so the compiler will be
>> quick to point mistakes.
>
> I think the "single name target only" rule should be in place no
> matter the syntax for the name binding operator itself.
>
> I don't mind too much either way on the mandatory parentheses question
> (it's certainly an easy option to actively discourage use of binding
> expressions as a direct alternative to assignment statements, but as
> with the single-name-only rule, it's independent of the choice of
> syntax)

Mandatory parenthesis around `(name := expr)` would at least solve the
problem of users mixing up '=' and ':=' in statements.

>
> I *do* think the "no name rebinding except in a while loop header"
> restriction would be annoying for the if/elif use case and the while
> use case:
>
> while (item = get_item()) is not first_delimiter:
> # First processing loop
> while (item = get_item()) is not second_delimiter:
> # Second processing loop
> # etc...
>
> if (target = get_first_candidate()) is not None:
> ...
> elif (target = get_second_candidate()) is not None:
> ...
> elif (target = get_third_candidate()) is not None:
> ...

Yes, it would force users to come up with better names *iff* they want
to use this new sugar:

  if (first_target = get_first_candidate()) ...
  elif (second_target = get_second_candidate()) ...

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Steven D'Aprano
On Tue, Apr 24, 2018 at 11:03:35AM -0400, Yury Selivanov wrote:

> My point was that when you see lots of '=' and ':=' used at the
> statement level, one might try to write "if x = 1" instead of "if x :=
> 1" -- boom, we have an unexpected SyntaxError for some users.

That's a *good* thing. They will then learn not to write x = 1 as an 
expression.

Also, if I write lots of x := 1 binding-expressions as statements, my 
code is bad and deserves to fail code-review. But why would I write the 
extra colon (one character, two key-presses) to use

x := 1

as a statement, when x = 1 will work? That's a sure sign that I don't 
know what I'm doing. (Or that I desperately wish I was writing Pascal.)

I don't think we need worry about this. The sort of code that is filled 
with binding-expressions used as statements will almost certainly be so 
un-Pythonic and ugly in many other ways, that this won't make any 
difference.


> In my opinion adding *any* assignment expression syntax to Python
> *will* create this sort of issues.  PEP 572 isn't free of them, my
> proposal isn't free of them.  My proposal doesn't add a new ':='
> operator at the cost of slightly complicating rules around '='.  PEP
> 572 avoids complicating '=', but adds an entirely new form of
> assignment.

Indeed. That is true: either way, we introduce complexity into the 
language. (But that will allow us to reduce complexity in *our* code.) 
Given that increasing complexity is inevitable regardless of whether we 
choose PEP 572 or your suggestion, it is better to choose the option 
which keeps binding-expressions and assignment statements separate, 
since they are two different concepts.



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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Yury Selivanov
On Tue, Apr 24, 2018 at 11:15 AM, Steven D'Aprano  wrote:
[..]

>> >> 3. Most importantly: it is *not* allowed to mask names in the current
>> >> local scope.
>
> That means you can't rebind existing variables. That means you can't
> rebind to the same variable in a loop.

No, it doesn't. The check is performed during compile phase, and
Python does not unroll loops. Anyways, read below.

> I believe that one of the most important use-cases for binding-
> expression syntax is while loops, like this modified example taken from
> PEP 572 version 3:
>
> while (data = sock.read()):
> print("Received data:", data)
>
> If you prohibit re-binding data, that prohibits cases like this, or even
> using it inside a loop:
>
> for value in sequence:
> process(arg, (item = expression), item+1)

No it doesn't. symtable in Python works differently. I encourage you
to test my reference implementation:

py> for val in [1, 2, 3]:
...   print((item=val), item+1)
...
1 2
2 3
3 4

> Why is this allowed?
>
> x = 1  # both are statement forms
> x = 2
>
> but this is prohibited?
>
> x = 1
> (x = 2)  # no rebinding is allowed
>
> and even more confusing, this is allowed!
>
> (x = 1)  # x doesn't exist yet, so it is allowed
> x = 2  # statement assignment is allowed to rebind

These all are very limited code snippets that you're unlikely to see
in real code.  I can write (and I did in this thread) a bunch of
examples of where PEP 572 is also inconsistent.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Nick Coghlan
On 25 April 2018 at 00:54, Eric Snow  wrote:
> Regardless, your 3 rules would benefit either syntax.  Nick may have a
> point that the rules might be an excessive burden, but I don't think
> it's too big a deal since the restrictions are few (and align with the
> most likely usage) and are limited to syntax so the compiler will be
> quick to point mistakes.

I think the "single name target only" rule should be in place no
matter the syntax for the name binding operator itself.

I don't mind too much either way on the mandatory parentheses question
(it's certainly an easy option to actively discourage use of binding
expressions as a direct alternative to assignment statements, but as
with the single-name-only rule, it's independent of the choice of
syntax)

I *do* think the "no name rebinding except in a while loop header"
restriction would be annoying for the if/elif use case and the while
use case:

while (item = get_item()) is not first_delimiter:
# First processing loop
while (item = get_item()) is not second_delimiter:
# Second processing loop
# etc...

if (target = get_first_candidate()) is not None:
...
elif (target = get_second_candidate()) is not None:
...
elif (target = get_third_candidate()) is not None:
...

And *that* rule is unique to the "=" spelling, since for other
proposals "lhs = rhs" in an expression is *always* a syntax error, and
you have to resolve the ambiguity in intent explicitly by either
adding a second "=" (to request equality comparison), or else some
other leading symbol (to request a binding expression).

Cheers,
Nick.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Yury Selivanov
On Tue, Apr 24, 2018 at 11:07 AM, Chris Angelico  wrote:
[..]

> x = 1
> if (x = 2): ...
>
> This, according to your proposal, raises SyntaxError - not because a
> comparison was wanted and an assignment was made, but because the name
> already had a value. And, even worse, this is NOT an error:

Yes, because I'm trying to think about this from a pragmatic side of
things. My question to myself: "what syntax could I use that would
prevent me from making '=' vs '==' mistake when I code?"  To me, the
answer is that I usually want to compare local variables.

When I compare to variables from outer scopes they *usually* are on
the *right* side of '=='.

>
> x = 1
> def f():
> if (x = 2):
> ...
>
> That's a bizarre distinction.

Chris, FWIW I'm trying to avoid using 'bizarre', 'arcane' etc with
regards to PEP 572 or any proposal, really. For example, I,
personally, find ':=' bizarre, but it's subjective and it's
unproductive to say that.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Steven D'Aprano
On Tue, Apr 24, 2018 at 09:50:34AM -0400, Yury Selivanov wrote:
> On Tue, Apr 24, 2018 at 9:46 AM, Nick Coghlan  wrote:
> > On 24 April 2018 at 23:38, Yury Selivanov  wrote:
> >> I propose to use the following syntax for assignment expressions:
> >>
> >> ( NAME = expr )
> >>
> >> I know that it was proposed before and this idea was rejected, because
> >> accidentally using '=' in place of '==' is a pain point in
> >> C/C++/JavaScript.
> >>
> >> That said, I believe we can still use this syntax as long as we impose
> >> the following three restrictions on it:
> >>
> >> 1. Only NAME token is allowed as a single target.
> >>
> >> 2. Parenthesis are required.

There are many places where I would use parentheses even if they are 
not required, but being forced to use them when they're not and I don't 
want them is ugly.

I also question why you think this will help prevent accidentally 
writing = when you meant == (equality). Have you never written something 
like this?

if (x == y) or (a > b): ...

Yes, I know the parens are not strictly needed, since the precedence of 
`or` is lower than the comparison operators. But still, especially for 
complex comparisons, a few extra (round) brackets can improve 
readability.

So now we have:

if (x = y) or (a > b): ...  # oops


But the biggest problem with this is that it is ambiguous to the human 
reader. At a glance, I'm likely to read x=y in an expression as 
equality. If I notice that it is a single = sign, I'm never going to be 
sure whether it was a mistake or intentional until I study the rest of 
the function minutely.

The benefit of := is that if I see it, I can be pretty sure it was not a 
typo. It is hard to mistype == as := by accident, and they are visually 
distinct enough that I am not going to misread := as == .


> >> 3. Most importantly: it is *not* allowed to mask names in the current
> >> local scope.

That means you can't rebind existing variables. That means you can't 
rebind to the same variable in a loop.

I believe that one of the most important use-cases for binding- 
expression syntax is while loops, like this modified example taken from 
PEP 572 version 3:

while (data = sock.read()):
print("Received data:", data)

If you prohibit re-binding data, that prohibits cases like this, or even 
using it inside a loop:

for value in sequence:
process(arg, (item = expression), item+1)


Your suggestion to prohibit rebinding variables effectively makes them 
so crippled as to be useless to me.


> > While I agree this would be unambiguous to a computer, I think for
> > most humans it would be experienced as a confusing set of arcane and
> > arbitrary rules about what "=" means in Python.
> 
> I respectfully disagree.  There are no "arcane and confusing rules"
> about "=", it's rather simple:
> 
> "=" is always an assignment.

Why is this allowed?

x = 1  # both are statement forms
x = 2

but this is prohibited?

x = 1
(x = 2)  # no rebinding is allowed

and even more confusing, this is allowed!

(x = 1)  # x doesn't exist yet, so it is allowed
x = 2  # statement assignment is allowed to rebind


By the way, the check for existing variables cannot help to be either 
incomplete or incorrect if you try to do it at compile time:


from module import *
(x = 2)  # allowed or not allowed?


If you don't like wild-card imports, how about this:

if random.random() > 0.5:
spam = 1
else:
eggs = 1
(spam = 2)  # allowed or not? no way to tell at compile time


But doing the rebinding/shadowing check at runtime will slow down 
binding expressions, and lead to even more arcane and confusing results:

it = iter("abc")
while (obj = next(it)):
print(obj)


will print "a" on the first loop, but then raise an exception on 
the second time loop as obj now exists.



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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Chris Angelico
On Wed, Apr 25, 2018 at 12:58 AM, Yury Selivanov
 wrote:
> On Tue, Apr 24, 2018 at 10:49 AM, Paul Moore  wrote:
> [..]
 3. Most importantly: it is *not* allowed to mask names in the current
 local scope.
>>>
>>> While I agree this would be unambiguous to a computer, I think for
>>> most humans it would be experienced as a confusing set of arcane and
>>> arbitrary rules about what "=" means in Python.
>>
>> Also, there's the ambiguity and potential for misreading in the
>> opposite direction (accidentally *reading* = as == even though it
>> isn't):
>>
>> if (diff = x - x_base) and (g = gcd(diff, n)) > 1:
>>  return g
>
> Since 'diff' and 'g' must be new names according to rule (3), those
> who read the code will notice that both were not previously bound.
> Therefore both are new variables so it can't be a comparison.

That would not be true if this code were in a loop. Or do you have a
different definition of "not previously bound" that is actually a
syntactic feature? For instance:

if (x = 1):
x = 2

Legal? Not legal?

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Chris Angelico
On Wed, Apr 25, 2018 at 1:03 AM, Yury Selivanov  wrote:
> On Tue, Apr 24, 2018 at 10:56 AM, Chris Angelico  wrote:
> [..]
>>> A lot of other questions arise though.  PEP 572 proposes:
>>>
>>> a = 1  # assignment
>>> a := 1  # also assignment
>>> (a := 1)  # also assignment
>>> (a = 1)  # error, why?
>>
>> Your third example is just the same as the second, with parentheses
>> around it. In most of Python, parentheses (if legal) have no effect
>> other than grouping; "a + b * c" is the same thing as "(a + b) * c",
>> just done in the other order. The last one is a clear demonstration
>> that "=" is a statement, not an expression. Are people confused by
>> this sort of thing:
>>
>> if x > 1:
>> print("x is more than 1")
>> (if x > 1:)
>> print("SyntaxError")
>
> This is a very far-fetched example :)

Heh, yes it is. But my point is that the parens are not creating a
weird situation here. They're just showcasing a distinction: one of
these is a statement, the other an expression. Which is the entire
point of the different operator - one is a syntactic feature of a
statement that creates one or more name bindings, the other is a
binary operator which results in a name binding as well as a value.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Paul Moore
On 24 April 2018 at 15:58, Yury Selivanov  wrote:
> On Tue, Apr 24, 2018 at 10:49 AM, Paul Moore  wrote:
> [..]
 3. Most importantly: it is *not* allowed to mask names in the current
 local scope.
>>>
>>> While I agree this would be unambiguous to a computer, I think for
>>> most humans it would be experienced as a confusing set of arcane and
>>> arbitrary rules about what "=" means in Python.
>>
>> Also, there's the ambiguity and potential for misreading in the
>> opposite direction (accidentally *reading* = as == even though it
>> isn't):
>>
>> if (diff = x - x_base) and (g = gcd(diff, n)) > 1:
>>  return g
>
> Since 'diff' and 'g' must be new names according to rule (3), those
> who read the code will notice that both were not previously bound.
> Therefore both are new variables so it can't be a comparison.

That was essentially my point, though - I can no longer read that line
of code in isolation from the surrounding context. Consider something
like a github PR review screen, where surrounding unchanged code is
frequently hidden.

Anyway, we can agree to differ on this - I don't like this idea and
I'd personally find it hard to read, but as you've already pointed
out, this is all extremely subjective.
Paul
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Yury Selivanov
On Tue, Apr 24, 2018 at 10:54 AM, Anthony Flury via Python-Dev
 wrote:
[..]
> As discussed previously by others on this exact proposals, you now have the
> issue of  confusion when using keyword arguments : *my_func(a = b)* :
> clearly that is a call to `my_func' where argument a has the value of b, but
> if you want to do an assigment expression when calling the function you now
> have to do *my_func((a=b)) -* which frankly looks messy in my opinion; you
> get the same issue when you are wanting to do assignment expressions in
> tuples.

Well, `my_func(a=(b:=foo))` or `my_func(b:=foo)` are also barely
readable to my eye.  My expectation is that users won't use any form
of assignment expressions in function calls, it's painful with both
proposals.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Chris Angelico
On Wed, Apr 25, 2018 at 12:54 AM, Anthony Flury via Python-Dev
 wrote:
> As discussed previously by others on this exact proposals, you now have the
> issue of  confusion when using keyword arguments : *my_func(a = b)* :
> clearly that is a call to `my_func' where argument a has the value of b, but
> if you want to do an assigment expression when calling the function you now
> have to do *my_func((a=b)) -* which frankly looks messy in my opinion; you
> get the same issue when you are wanting to do assignment expressions in
> tuples.

To be fair, function arguments already follow "practicality beats
purity" in many ways. Let's look at tuples:

x = 1, 2 # fine
x = (1, 2) # fine
x = 1, # fine, though not advisable
x = (1,) # fine

But if you're going to use a tuple literal as a function parameter,
you have to give it extra parens:

f((1, 2)) # one arg, a tuple
f(1, 2) # two args

The comma has multiple meanings, and it has to be disambiguated. The
equals sign would be the same.

I'm still strongly -1 on any proposal to have "=" mean assignment in
any expression context, though. It is WAY too easy for a comparison to
sneakily become an assignment, or to get bizarre syntax errors:

x = 1
if (x = 2): ...

This, according to your proposal, raises SyntaxError - not because a
comparison was wanted and an assignment was made, but because the name
already had a value. And, even worse, this is NOT an error:

x = 1
def f():
if (x = 2):
...

That's a bizarre distinction.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Yury Selivanov
On Tue, Apr 24, 2018 at 10:49 AM, Paul Moore  wrote:
[..]
>>> 3. Most importantly: it is *not* allowed to mask names in the current
>>> local scope.
>>
>> While I agree this would be unambiguous to a computer, I think for
>> most humans it would be experienced as a confusing set of arcane and
>> arbitrary rules about what "=" means in Python.
>
> Also, there's the ambiguity and potential for misreading in the
> opposite direction (accidentally *reading* = as == even though it
> isn't):
>
> if (diff = x - x_base) and (g = gcd(diff, n)) > 1:
>  return g

Since 'diff' and 'g' must be new names according to rule (3), those
who read the code will notice that both were not previously bound.
Therefore both are new variables so it can't be a comparison.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Eric Snow
Thanks for thinking this through, Yury. :)

FWIW, I'm still unconvinced that an assignment expression is worth it.
It's hard to say, though, without seeing how much folks would actually
use it (and I don't have my own time machine unfortunately).  IIRC, in
the past several proposed syntax (e.g. decorators) were in the same
boat and in retrospect turned out to be a strongly positive addition
to the language. :)

Comments in-line below.

-eric

On Tue, Apr 24, 2018 at 7:38 AM, Yury Selivanov  wrote:
> I propose to use the following syntax for assignment expressions:
>
> ( NAME = expr )
>
> [snip]
>
> 1. Only NAME token is allowed as a single target.

This seems reasonable and does keep assignment expressions easier for
the reader to find.  At the same time, there have been some arguments
elsewhere in favor of tuple unpacking as the other obvious use case.
Presumably that would not be supported under this rule.

> 2. Parenthesis are required.

Similar to rule #1, this would make assignment expressions more
obvious to readers, which is a good thing.

>
> 3. Most importantly: it is *not* allowed to mask names in the current
> local scope.

I was about to leave this counter example for
accidentally-typed-one-equal-sign-instead-of-two bugs:

if (y == 3):
print(y)
# vs.
if (y = 3):
print(y)

Then it dawned on me that your rule #3 solves this. :)

> [snip]
>
> py> f = lambda x: x * 10
> py> [[(y = f(x)), x/y] for x in range(1,5)]
> [[10, 0.1], [20, 0.1], [30, 0.1], [40, 0.1]]
>
> [snip]
>
> I believe that this syntax is the best of both worlds: it allows to
> write succinct code just like PEP 572, but without introducing a new
> ':=' operator.

This is the main point of this alternate proposal, right?  It
certainly seems reasonable that we not add another assignment syntax.
On the other hand, having ":=" as a distinct syntax for assignment
expressions is close enough to the existing syntax that it doesn't
really add any real extra burden to readers, while being more
searchable and visually distinct.  If we were to add assignment
expressions I'd probably favor ":=".

Regardless, your 3 rules would benefit either syntax.  Nick may have a
point that the rules might be an excessive burden, but I don't think
it's too big a deal since the restrictions are few (and align with the
most likely usage) and are limited to syntax so the compiler will be
quick to point mistakes.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Yury Selivanov
On Tue, Apr 24, 2018 at 10:56 AM, Chris Angelico  wrote:
[..]
>> A lot of other questions arise though.  PEP 572 proposes:
>>
>> a = 1  # assignment
>> a := 1  # also assignment
>> (a := 1)  # also assignment
>> (a = 1)  # error, why?
>
> Your third example is just the same as the second, with parentheses
> around it. In most of Python, parentheses (if legal) have no effect
> other than grouping; "a + b * c" is the same thing as "(a + b) * c",
> just done in the other order. The last one is a clear demonstration
> that "=" is a statement, not an expression. Are people confused by
> this sort of thing:
>
> if x > 1:
> print("x is more than 1")
> (if x > 1:)
> print("SyntaxError")

This is a very far-fetched example :)

My point was that when you see lots of '=' and ':=' used at the
statement level, one might try to write "if x = 1" instead of "if x :=
1" -- boom, we have an unexpected SyntaxError for some users.

In my opinion adding *any* assignment expression syntax to Python
*will* create this sort of issues.  PEP 572 isn't free of them, my
proposal isn't free of them.  My proposal doesn't add a new ':='
operator at the cost of slightly complicating rules around '='.  PEP
572 avoids complicating '=', but adds an entirely new form of
assignment.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Anthony Flury via Python-Dev

On 24/04/18 14:50, Yury Selivanov wrote:

On Tue, Apr 24, 2018 at 9:46 AM, Nick Coghlan  wrote:

On 24 April 2018 at 23:38, Yury Selivanov  wrote:

I propose to use the following syntax for assignment expressions:

 ( NAME = expr )

I know that it was proposed before and this idea was rejected, because
accidentally using '=' in place of '==' is a pain point in
C/C++/JavaScript.

That said, I believe we can still use this syntax as long as we impose
the following three restrictions on it:

1. Only NAME token is allowed as a single target.

2. Parenthesis are required.

3. Most importantly: it is *not* allowed to mask names in the current
local scope.

While I agree this would be unambiguous to a computer, I think for
most humans it would be experienced as a confusing set of arcane and
arbitrary rules about what "=" means in Python.

I respectfully disagree.  There are no "arcane and confusing rules"
about "=", it's rather simple:

"=" is always an assignment.

But it isn't - in your proposed syntax :

 * * = * is an assignment with no return value
 * *( = )* is an assignment with a returned value

  So now '=' is always an assignment, it is an assignment with extra 
semantics depending on surrounding syntax.


As discussed previously by others on this exact proposals, you now have 
the issue of  confusion when using keyword arguments : *my_func(a = b)* 
: clearly that is a call to `my_func' where argument a has the value of 
b, but if you want to do an assigment expression when calling the 
function you now have to do *my_func((a=b)) -* which frankly looks messy 
in my opinion; you get the same issue when you are wanting to do 
assignment expressions in tuples.


Using a different operator for assignments which return values avoids 
the messy potentially multiple level brackets, and means that the 
semantics of an operator depends only on that operator and not on syntax 
elements before and after it.


--
--
Anthony Flury
email : *anthony.fl...@btinternet.com*
Twitter : *@TonyFlury *

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Chris Angelico
On Wed, Apr 25, 2018 at 12:23 AM, Yury Selivanov
 wrote:
> On Tue, Apr 24, 2018 at 10:07 AM, Nick Coghlan  wrote:
>
>>> "=" is always an assignment.
>>> "==" is always an equality check.
>>
>> That's not the distinction I meant, I meant the difficulty of
>> explaining the discrepancies in this list:
>>
>> a = 1 # Assignment
>> (a = 1) # Also assignment
>>
>> a, b = 1, 2 # Tuple assignment
>> (a, b = 1, 2) # SyntaxError. Why?
>>
>> ...
>> Whereas if binding expressions use a different symbol, the question is
>> far less likely to arise, and if it does come up, then the answer is
>> the same as the one for def statements vs lambda expressions: because
>> one is a statement, and the other is an expression.
>
> A lot of other questions arise though.  PEP 572 proposes:
>
> a = 1  # assignment
> a := 1  # also assignment
> (a := 1)  # also assignment
> (a = 1)  # error, why?

Your third example is just the same as the second, with parentheses
around it. In most of Python, parentheses (if legal) have no effect
other than grouping; "a + b * c" is the same thing as "(a + b) * c",
just done in the other order. The last one is a clear demonstration
that "=" is a statement, not an expression. Are people confused by
this sort of thing:

if x > 1:
print("x is more than 1")
(if x > 1:)
print("SyntaxError")

? Yes, the word 'if' does have meaning in an expression context, and
yes, it has a similar meaning to the 'if' statement, but people don't
parenthesize entire statements. You try that with assignment, you get
an error, and bam, it's obvious that you ran into this particular
case.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Nick Coghlan
On 25 April 2018 at 00:23, Yury Selivanov  wrote:
> A lot of other questions arise though.  PEP 572 proposes:
>
> a = 1  # assignment
> a := 1  # also assignment
> (a := 1)  # also assignment
> (a = 1)  # error, why?

That's just the typical assignment/expression dichotomy, though, which
is genuinely confusing for learners (since expression-level Python and
statement-level Python allow different constructs), but also not a new
problem.

All the other keywords that have both statement level and expression
level use cases are structured as prefix operators in statement form,
and some kind of infix operator in expression form, whereas this would
be the first case where we offered a construct that used infix syntax
for both its statement form and its expression form.

> It's also difficult to explain which one to use when.  The net result
> is that code will be littered with both at random places.  That will
> decrease the readability of Python code at least for some users who
> have similar taste to myself.

That's a legitimate concern with PEP 572 (and part of why I'm
somewhere between -1 and -0 on the ":=" spelling, although I'd be +0
on an "is=" spelling that riffs off the "is" comparison operator -
using the "name is= expr" spelling in place of a regular assignment
looks sufficiently odd that I'd expect the temptation to write it in
place of "name = expr" when the latter is permitted would be low)

> With '=' in expressions, the code will look uniform.  There will be a
> simple rule to put parens around assignments in expression and use
> simple names.  After one or two descriptive SyntaxError users will
> learn how this syntax works (like people learn everything in coding).

Except that they'll also find other discrepancies like:

a = 1
a = 2

being OK, while:

a = 1
(a = 2)

fails with SyntaxError on the second line.

Cheers,
Nick.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Paul Moore
On 24 April 2018 at 14:46, Nick Coghlan  wrote:
> On 24 April 2018 at 23:38, Yury Selivanov  wrote:
>> I propose to use the following syntax for assignment expressions:
>>
>> ( NAME = expr )
>>
>> I know that it was proposed before and this idea was rejected, because
>> accidentally using '=' in place of '==' is a pain point in
>> C/C++/JavaScript.
>>
>> That said, I believe we can still use this syntax as long as we impose
>> the following three restrictions on it:
>>
>> 1. Only NAME token is allowed as a single target.
>>
>> 2. Parenthesis are required.
>>
>> 3. Most importantly: it is *not* allowed to mask names in the current
>> local scope.
>
> While I agree this would be unambiguous to a computer, I think for
> most humans it would be experienced as a confusing set of arcane and
> arbitrary rules about what "=" means in Python.

Also, there's the ambiguity and potential for misreading in the
opposite direction (accidentally *reading* = as == even though it
isn't):

if (diff = x - x_base) and (g = gcd(diff, n)) > 1:
 return g

My immediate reading of this is as an equality comparison between diff
and x - x_base (which would send me futilely looking for a definition
of diff) and an equality comparison of g and gcd(diff, n)... wait, why
am I doing (equality comparison) > 1? Oh, hang on... At this point,
any hope of me quickly understanding what this code does is lost.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Yury Selivanov
On Tue, Apr 24, 2018 at 10:07 AM, Nick Coghlan  wrote:

>> "=" is always an assignment.
>> "==" is always an equality check.
>
> That's not the distinction I meant, I meant the difficulty of
> explaining the discrepancies in this list:
>
> a = 1 # Assignment
> (a = 1) # Also assignment
>
> a, b = 1, 2 # Tuple assignment
> (a, b = 1, 2) # SyntaxError. Why?
>
> ...
> Whereas if binding expressions use a different symbol, the question is
> far less likely to arise, and if it does come up, then the answer is
> the same as the one for def statements vs lambda expressions: because
> one is a statement, and the other is an expression.

A lot of other questions arise though.  PEP 572 proposes:

a = 1  # assignment
a := 1  # also assignment
(a := 1)  # also assignment
(a = 1)  # error, why?

It's also difficult to explain which one to use when.  The net result
is that code will be littered with both at random places.  That will
decrease the readability of Python code at least for some users who
have similar taste to myself.

With '=' in expressions, the code will look uniform.  There will be a
simple rule to put parens around assignments in expression and use
simple names.  After one or two descriptive SyntaxError users will
learn how this syntax works (like people learn everything in coding).

This all is very subjective.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Nick Coghlan
On 24 April 2018 at 23:50, Yury Selivanov  wrote:
> On Tue, Apr 24, 2018 at 9:46 AM, Nick Coghlan  wrote:
>> On 24 April 2018 at 23:38, Yury Selivanov  wrote:
>>> I propose to use the following syntax for assignment expressions:
>>>
>>> ( NAME = expr )
>>>
>>> I know that it was proposed before and this idea was rejected, because
>>> accidentally using '=' in place of '==' is a pain point in
>>> C/C++/JavaScript.
>>>
>>> That said, I believe we can still use this syntax as long as we impose
>>> the following three restrictions on it:
>>>
>>> 1. Only NAME token is allowed as a single target.
>>>
>>> 2. Parenthesis are required.
>>>
>>> 3. Most importantly: it is *not* allowed to mask names in the current
>>> local scope.
>>
>> While I agree this would be unambiguous to a computer, I think for
>> most humans it would be experienced as a confusing set of arcane and
>> arbitrary rules about what "=" means in Python.
>
> I respectfully disagree.  There are no "arcane and confusing rules"
> about "=", it's rather simple:
>
> "=" is always an assignment.
> "==" is always an equality check.

That's not the distinction I meant, I meant the difficulty of
explaining the discrepancies in this list:

a = 1 # Assignment
(a = 1) # Also assignment

a, b = 1, 2 # Tuple assignment
(a, b = 1, 2) # SyntaxError. Why?

a.b = 1 # Attribute assignment
(a.b = 1) # SyntaxError. Why?

a[b] = 1 # Subscript assignment
(a[b] = 1) # SyntaxError. Why?


(a=1), (b=2) # Two assignments
a=1, b=2 # SyntaxError. Why?

f(a=1, b=2) # Function call with keyword args
(a=1, b=2) # SyntaxError. Why?

if (a=1): pass # Assignment
if a=1: pass # SyntaxError. Why?

Whereas if binding expressions use a different symbol, the question is
far less likely to arise, and if it does come up, then the answer is
the same as the one for def statements vs lambda expressions: because
one is a statement, and the other is an expression.

Cheers,
Nick.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Antoine Pitrou
On Tue, 24 Apr 2018 23:46:34 +1000
Nick Coghlan  wrote:
> On 24 April 2018 at 23:38, Yury Selivanov  wrote:
> > I propose to use the following syntax for assignment expressions:
> >
> > ( NAME = expr )
> >
> > I know that it was proposed before and this idea was rejected, because
> > accidentally using '=' in place of '==' is a pain point in
> > C/C++/JavaScript.
> >
> > That said, I believe we can still use this syntax as long as we impose
> > the following three restrictions on it:
> >
> > 1. Only NAME token is allowed as a single target.
> >
> > 2. Parenthesis are required.
> >
> > 3. Most importantly: it is *not* allowed to mask names in the current
> > local scope.  
> 
> While I agree this would be unambiguous to a computer, I think for
> most humans it would be experienced as a confusing set of arcane and
> arbitrary rules about what "=" means in Python.

If the ambition is to find a piece of syntax that reads as "binds",
then we can use a variation on the FLUFL operator: "<->".

Regards

Antoine.


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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Yury Selivanov
On Tue, Apr 24, 2018 at 9:46 AM, Nick Coghlan  wrote:
> On 24 April 2018 at 23:38, Yury Selivanov  wrote:
>> I propose to use the following syntax for assignment expressions:
>>
>> ( NAME = expr )
>>
>> I know that it was proposed before and this idea was rejected, because
>> accidentally using '=' in place of '==' is a pain point in
>> C/C++/JavaScript.
>>
>> That said, I believe we can still use this syntax as long as we impose
>> the following three restrictions on it:
>>
>> 1. Only NAME token is allowed as a single target.
>>
>> 2. Parenthesis are required.
>>
>> 3. Most importantly: it is *not* allowed to mask names in the current
>> local scope.
>
> While I agree this would be unambiguous to a computer, I think for
> most humans it would be experienced as a confusing set of arcane and
> arbitrary rules about what "=" means in Python.

I respectfully disagree.  There are no "arcane and confusing rules"
about "=", it's rather simple:

"=" is always an assignment.
"==" is always an equality check.

Having two assignment operators feels way more arcane to me.
Especially in Python guided by "there should be one way" Zen.

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


Re: [Python-Dev] assignment expressions: an alternative proposal

2018-04-24 Thread Nick Coghlan
On 24 April 2018 at 23:38, Yury Selivanov  wrote:
> I propose to use the following syntax for assignment expressions:
>
> ( NAME = expr )
>
> I know that it was proposed before and this idea was rejected, because
> accidentally using '=' in place of '==' is a pain point in
> C/C++/JavaScript.
>
> That said, I believe we can still use this syntax as long as we impose
> the following three restrictions on it:
>
> 1. Only NAME token is allowed as a single target.
>
> 2. Parenthesis are required.
>
> 3. Most importantly: it is *not* allowed to mask names in the current
> local scope.

While I agree this would be unambiguous to a computer, I think for
most humans it would be experienced as a confusing set of arcane and
arbitrary rules about what "=" means in Python.

Cheers,
Nick.

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