<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">2018-04-12 1:43 GMT+03:00 Chris Angelico <span dir="ltr"><<a href="mailto:rosuav@gmail.com" target="_blank">rosuav@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Thu, Apr 12, 2018 at 5:24 AM, Kirill Balunov <<a href="mailto:kirillbalunov@gmail.com">kirillbalunov@gmail.com</a>> wrote:<br>
> I find that I wrote very vague, so I'll try in response to my answer to add<br>
> some specifics. In general, I find this idea missed in the language and<br>
> thank you for trying to fix this! In my opinion it has only a meaning in<br>
> certain constructions such as `while`, `if`, `elif` and maybe<br>
> comprehensions\generators. As a general form "anywhere" it can be _useful_,<br>
> but makes the code unreadable and difficult to perceive while giving not so<br>
> much benefit. What I find nice to have:<br>
><br>
> Extend while statement syntax:<br>
><br>
>  while (input("> ") as command) != "quit":<br>
>      print("You entered:", command)<br>
<br>
</span>What you're writing there is not truly an extension of the while<br>
statement, but a special feature of an expression *within* the while<br>
header. </blockquote><div><br>
All right! 
<span id="gmail-result_box" class="gmail-short_text" lang="en"><span class="gmail-">You caught me </span></span>:) 
<span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-">For lack of a thoughtful alternative version in my head, let it be</span></span> an expression 
<span id="gmail-result_box" class="gmail-short_text" lang="en"><span class="gmail-">but such that it can only be used (evaluated) in</span></span>
 boolean context: `while` and `if`s statements (let's skip 
comprehensions and generators for some time, except their `if` clause). I
 agree that it contradicts with the way that in 'with' or 'import' 
statements it is a part of their own syntax. 
<span id="gmail-result_box" class="gmail-short_text" lang="en"><span class="gmail-">But nonetheless</span></span> they have the same syntax but, <span id="gmail-result_box" class="gmail-short_text" lang="en"><span class="gmail-">strictly speaking</span></span>, different semantics! <span id="gmail-result_box" class="gmail-short_text" lang="en"><span class="gmail-">And this is normal, because they are different statements.</span></span>

<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Syntactically, this "expr as name" notation must be able to be<br>
combined with other operators (as in what you've written here), so it<br>
isn't like the way the 'with' or 'import' statement specifically makes<br>
a feature available as its own syntax.<span class=""><br></span></blockquote><div><br></div><div><span id="gmail-result_box" class="gmail-short_text" lang="en"><span class="gmail-">Ability to combine</span></span> `expr as name` with other operators -<span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"> is actually a matter of operator precedence. In my mind it should have the highest precedence: 
<span style="font-family:monospace,monospace"><span class="gmail-"><br></span></span></span></span></div><div style="margin-left:40px"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span style="font-family:monospace,monospace"><span class="gmail-">while input("> ") as command != "quit":</span></span> </span></span><br></div><div><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"></span></span><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"></span></span>is equivalent to 
<span style="font-family:monospace,monospace"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-"><br></span></span></span></span><div style="margin-left:40px"><span style="font-family:monospace,monospace"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-">while (input("> ") as command) != "quit":<br> </span></span></span></span><br></div><div style="margin-left:40px"><span style="font-family:monospace,monospace"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-"></span></span></span></span></div><span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-">Suppose that </span></span></span><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-">some function can return `empty tuple` and `None` (which are both False in boolean context), for this case you can write: <br></span></span></span></span><div style="margin-left:40px"><span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span style="font-family:monospace,monospace"><span class="gmail-">while func(something) as value is not None:</span></span></span></span>

<br></span></span></span></span></div><span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-">which is equivalent to <br></span></span></span></span><div style="margin-left:40px"><span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-">
<span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span style="font-family:monospace,monospace"><span class="gmail-">while (func(something) as value) is not None:</span></span></span></span></span></span></span></span>

</span></span></span></span><br></div><div style="margin-left:40px"><span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-"></span></span></span></span></div><span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-">and can be also written as: 
<br></span></span></span></span><div style="margin-left:40px"><span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-"><span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span style="font-family:monospace,monospace"><span class="gmail-">while (func(something) as value) or (value is not None): <br></span></span></span></span></span></span></span></span></span></span></span></span></div><span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-"><span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-">In the last snippet parenthesis were used only for readability.<br><br><br></span></span></span></span></span></span></span></span></span></span></span></div><div><span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-"><span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-">Another example:<br></span></span></span></span></span></span></span></span></span></span></span></div><div style="margin-left:40px"><span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-"><span style="font-family:arial,helvetica,sans-serif"><span style="font-family:monospace,monospace">while f1(x) + f2(x) as value:<br></span></span></span></span></span></span></div><span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-"><span style="font-family:arial,helvetica,sans-serif">will be parsed as:<br></span></span></span></span></span><div style="margin-left:40px"><span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-"><span style="font-family:arial,helvetica,sans-serif"><span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-"><span style="font-family:arial,helvetica,sans-serif"><span style="font-family:monospace,monospace">while f1(x) + (f2(x) as value):<br></span></span></span></span></span></span></span></span></span></span></span></div></div><div class="gmail_quote"><div><div style="margin-left:40px"><span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-"></span></span></span></span></div><span style="font-family:arial,helvetica,sans-serif"><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-"><span class="gmail-"> 
</span></span></span></span><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> Extend ternary expression syntax:<br>
><br>
> data = y/x if (f(x) as y) > 0 else 0<br>
<br>
</span>Again, this is doing further operations after the capturing, so it's<br>
not like you can incorporate it in the syntax. You can't write:<br>
<br>
expr2 if expr1 as NAME else expr3<br>
and explain its semantics that way, because then you can't put the "><br>
0" part in anywhere.<br></blockquote><div><br>
<span id="gmail-result_box" class="gmail-short_text" lang="en"><span class="gmail-">Do not quite understand why I can not?</span></span> :) (the parenthesis was used only for readability)<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
So if, syntactically, this is a modification to expressions in<br>
general, why restrict them to certain contexts? Why can't I lift the<br>
condition out of the 'while' and give it a name?<br>
<span class=""><br>
while (input("> ") as command) != "quit":<br>
</span># becomes #<br>
cond = (input("> ") as command) != "quit"<br>
print(cond)<br>
while cond:<br>
<br>
But I can't if this is magic in the 'while' statement. What do you<br>
gain by forbidding it?<br></blockquote><div><br></div><div>I gain readability! I don't see any reason to use it in other contexts... 
<span style="text-align:start;text-indent:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">Because it makes the code unreadable and difficult to perceive while giving not so much benefit. 
<span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-">I may be wrong, but so far I have not seen a single example that at least slightly changed my mind</span></span>. 
<span id="gmail-result_box" class="gmail-short_text" lang="en"><span class="gmail-">Concerning your example, I did not understand it</span></span>..`cond` is evaluated only once...why you need a while loop in this case?<br></span></div><div> <br></div><div> <span class=""></span><br><span class=""></span></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> I think that is all. And it seems to me that it covers 99% of all the<br>
> use-cases of this feature. In my own world I would like them to make a local<br>
> _statement_ binding (but this is certainly a very controversial point). I<br>
> even like that this syntax matches the `with` an `except` statements syntax,<br>
> although it has a different semantic. But I do not think that anyone will<br>
> have problems with perception of this.<br>
<br>
</span>Statement-local names, controversial? You don't say!<br>
<br>
I actually think the parallel with 'with' and 'except' works *against*<br>
that version of the proposal, precisely because of the different<br>
semantics (as you mention). The difference between:<br>
<br>
except Exception as e:<br>
except (Exception as e):<br>
<br></blockquote><div><br></div><div>It **will not be allowed** in `except` since there is no boolean context... 
<span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-">There 
is no parallels, only the same syntax, it seems to me that no one will 
have problems understanding what that means in different contexts. 
<span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-">In addition, at the moment all are coping with the differences between `import`, `with` and `except`.</span></span>

<br></span></span> <br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
is significant and fairly easy to spot; as soon as you try to use 'e',<br>
you'll figure out that it's the Exception class, not the instance that<br>
got thrown. But in a 'with' statement?<br>
<br>
with open(fn) as f:<br>
with (open(fn) as f):<br>
<br>
These will do the same thing, because Python's file objects return<br>
self from __enter__. So do a lot of context managers. You can go a<br>
VERY long way down this rabbit-hole, doing things like:<br>
<br>
with (open(infile) as read and<br>
        open(outfile, "w") as write):<br>
    write.write(read.read())<br>
<br>
In CPython, you likely won't notice anything wrong here. And hey, it's<br>
backslash-free multi-line context management! In fact, you might even<br>
be able to use this in *Jython* without noticing a problem. Until you<br>
have two output files, and then stuff breaks badly. Thus I sought to<br>
outright forbid 'as' in the expressions used in a 'with' or 'except'<br>
statement. </blockquote><div><br></div><div>The same goes for `with` statements, 
<span id="gmail-result_box" class="gmail-short_text" lang="en"><span class="gmail-">I see no reason to use both</span></span> `:=` and `expr as name` in with statements. How this feature can be used here, especially in the context you mentioned above? <br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The problem doesn't exist with ':=', because it's clear<br>
that the different semantics go with different syntax:<br>
<br>
with open(fn) as f:<br>
with f := open(fn):<br>
<br>
And since there's no reason to restrict it, it's open to all contexts<br>
where an expression s needed.<br>
</blockquote><div><br></div><div> As for me this example 
<span id="gmail-result_box" class="gmail-short_text" lang="en"><span class="gmail-">just shows that </span></span>`:=` 
<span id="gmail-result_box" class="gmail-short_text" lang="en"><span class="gmail-">should not be used</span></span> in `with` statements at all.<br><br>
<span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-">I ask 
you to understand me correctly, but what surprised me most, was that 
different versions of PEP (3 and 4) speaks about absolutely different things. 
<span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-alt-edited">I think it would be great to have two competing proposals:</span></span>

<br>1. 
<span id="gmail-result_box" class="gmail-short_text" lang="en"><span class="gmail-">This PEP in the form that is now</span></span> (with general assignment expression)<br>2. 
<span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-">Another PEP which discusses only the changes in if and while statements</span></span>.<br>
<span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-">I understand that it is much easier to advise than to do!</span> <span class="gmail-">I also understand how much time it takes for all this.</span> <span class="gmail-">I myself still can not find the time (English is given to me with great difficulty :))</span><span class="gmail-"> to write about PEP about partial assignment statement ...</span></span>

<br>
<span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-">But 
still, as I see these two PEPs will allow to simultaneously look at 
the two approaches, and also allow to separately work through the 
problems arising in each of them.</span></span>


<span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-">I do not want to repeat it again, but I have not yet seen any reasonable example where this current `:=` feature can be useful, except `while` and `if`.</span></span>


<span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-">So I do not understand why everything needs to be complicated and not concentrate on what can actually be useful</span></span>.<br><br></span></span></div><div><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-">With kind regards,<br></span></span></div><div><span id="gmail-result_box" class="gmail-" lang="en"><span class="gmail-">-gdg<br></span></span></div></div><br></div></div>