<div dir="ltr"><div>This seems more suitable for a style guide.</div><div><br></div><div>Enforcing such restrictions in the grammar would actually be complicated, due to nesting -- but even if it wasn't, I wouldn't want to, as I don't want to limit future generations to only the benefits of the new construct that we can now come up with. Orthogonality is a good thing in my mind, else we might never have had nested functions or conditional imports.<br></div><div><br></div><div>As to why you might want to use := in a function call, I could imagine writing</div><div><br></div><div>    if validate(name := re.search(pattern, line).group(1)):</div><div>        return name</div><div><br></div><div>The benefit of combining the assignment with the if would be more apparent if there was an if-elif...elif-else pattern, like here:</div><div><a href="https://github.com/python/peps/pull/695/files#diff-09a4f112ea673a2339f0bec6014ff47fR409">https://github.com/python/peps/pull/695/files#diff-09a4f112ea673a2339f0bec6014ff47fR409</a> (click off the comments to see it better).<br></div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr">On Sat, Jul 7, 2018 at 6:12 AM Giampaolo Rodola' <<a href="mailto:g.rodola@gmail.com">g.rodola@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div>Sorry in advance for opening yet another topic about PEP-572. With PEP-572 being officially accepted I know debating its inclusion in the language is a useless exercise at this point, but since it's still in "draft" status I would like to express my opinion as I think this is a feature which can potentially be abused fairly easily. FWIW I initially found myself disliking the idea as a whole but <a href="https://github.com/python/cpython/pull/8122" target="_blank">https://github.com/python/cpython/pull/8122</a> made me (and others) reconsider it quite a bit (see: <a href="https://twitter.com/grodola/status/1015251302350245888" target="_blank">https://twitter.com/grodola/status/1015251302350245888</a>). PR-8122 clearly shows an improvement in expressiveness and compactness (many folks argue this is too much) but PEP-572 as it currently stands is too permissive IMHO. My concern about "easily abusable ugly cases" still remains, and I think they should be banned instead of just discouraged in the PEP or in the doc. Since we spend way more time *reading* code rather than writing it, as a "reader" I would expect a more prudent approach to the problem.</div><div><br></div><div>Proposal</div><div>========</div><div><br></div><div>1) allow only one := assignment per line in "if" statements:</div><div>    >>> if x := val1 and y := val2:   # SyntaxError or SyntaxWarning</div><div>    >>> if x == val1 and y := val2:   # SyntaxError or SyntaxWarning</div><div><span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">    >>> if x := val1 and y == val2:   # SyntaxError or SyntaxWarning</span></div><div><span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">    >>> if x := val1:  # OK</span></div><div><span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">    >>> if (x := val1):  # OK</span><br></div><div><span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><br></span></div><div>2) allow := in "while" statements, "if" statements and comprehensions only:</div><div>    >>> foo(x := 0)  # SyntaxError</div><div>    >>> yield x := 3  # SyntaxError</div><div>    >>> assert y := 3  # SyntaxError</div><div><br></div><div>3) (debatable) disallow := if the variable is already defined:</div><div>    >>> x = 5</div><div>    >>> if (x := val):  # SyntaxError or SyntaxWarning</div><div><br></div><div>4) ban "a = (b := c)", "x = a := (b := (c := d))" and similar (they're just too ugly IMHO)</div><div><br></div><div>Rationale 1</div><div>===========</div><div><br></div><div>In visual terms assignments in Python have always occurred at the BEGINNING of the line and always on the most LEFT side:</div><div><br></div><div>    >>> foo = fun1()</div><div>    >>> bar = fun2()</div><div>    >>> baz = fun3()</div><div><br></div><div>That is where I naturally expect an assignment to be when reading code. My main concern with PEP-572 is that an assignments can now occur at *any point* in the line:</div><div><br></div><div>    >>> foo = fun1()</div><div>    >>> bar = fun2()</div><div>    >>> if foo == val1 and bar == val2 and baz := fun3():</div><div>    ...    ...</div><div><br></div><div>That forces me to visually scan the whole line horizontally from left to right 'till its end, looking for possible variables being set. I'm concerned that I will miss := occurrences because visually they are very similar to == unless parentheses are made mandatory:</div><div><br></div><div>    >>> if foo == val1 and bar == val2 and (baz := fun3()):</div><div>    ...    ...</div><div><br></div><div>Also, in case of multi-line conditionals I have to visually scan the construct both horizontally AND vertically:</div><div><br></div><div>    >>> if (foo == val1 and \</div><div>    ...        bar == val2 and \</div><div>    ...        baz := val3):</div><div>    ...     ...</div><div><br></div><div>Again, that is not a place where I would expect to find or look for a variable assignment. I know I wouldn't like to read or review a code which does that and I suspect linters will likely end up wanting to emit a warning in that case (see: <a href="https://github.com/PyCQA/pylint/issues/2246" target="_blank">https://github.com/PyCQA/pylint/issues/2246</a>). <a href="https://github.com/python/cpython/pull/8116/files" target="_blank">https://github.com/python/cpython/pull/8116/files</a> avoids using multiple := per line and that's why the result appears readable enough IMO. </div><div><br></div><div>Rationale 2</div><div>===========</div><div><br></div><div>PEP-572 states:</div><div><br></div><div>    > The := operator may be used directly in a positional function call argument</div><div><br></div><div>That means allowing:</div><div><br></div><div>    >>> foo(x := 0)</div><div><br></div><div>I honestly don't see why anyone would want to call a function AND assign a variable value at the same time (except in comprehensions). With this in place I not only have to guard against "if" statements assigning values at any point in the code, but also function calls, both horizontally and vertically e.g.:</div><div><br></div><div>    >>> foo(some_long_var_name, another_one, x := bar(),</div><div>            y := fun())</div><div><br></div><div>To me this looks like the perfect example of where this functionality can be abused. Also, I'm not clear what PEP-572 intend to do about "all other places". E.g. should these cases be allowed? (IMO no)</div><div><br></div><div>    >>> yield x := 3</div><div>    >>> assert y := 3</div><div><br></div><div>--</div><div>Giampaolo - <a href="http://grodola.blogspot.com" target="_blank">http://grodola.blogspot.com</a></div></div><div><br></div></div>
_______________________________________________<br>
Python-Dev mailing list<br>
<a href="mailto:Python-Dev@python.org" target="_blank">Python-Dev@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-dev" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/python-dev</a><br>
Unsubscribe: <a href="https://mail.python.org/mailman/options/python-dev/guido%40python.org" rel="noreferrer" target="_blank">https://mail.python.org/mailman/options/python-dev/guido%40python.org</a><br>
</blockquote></div><br clear="all"><br>-- <br><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido">python.org/~guido</a>)</div>