<div dir="ltr">Thanks! Perhaps the most useful bit of this post is the clear list of use cases (a useful summary of the motivational part of PEP 572).<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, May 4, 2018 at 5:06 AM, Nick Coghlan <span dir="ltr"><<a href="mailto:ncoghlan@gmail.com" target="_blank">ncoghlan@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div>(Note: Guido's already told me off-list that he doesn't like the way this spelling reads, but I wanted to share it anyway since it addresses one of the recurring requests in the PEP 572 discussions for a more targeted proposal that focused specifically on the use cases that folks had agreed were reasonable potential use cases for inline assignment expressions.<br><br></div><div>I'll also note that another potential concern with this specific proposal is that even though "given" wasn't used as a term in any easily discovered Python APIs back when I first wrote PEP 3150, it's now part of the Hypothesis testing API, so adopting it as a keyword now would be markedly more disruptive than it might have been historically)<br><br></div>Recapping the use cases where the inline assignment capability received the most agreement regarding being potentially more readable than the status quo:<br><br></div>1. Making an "exactly one branch is executed" construct clearer than is the case for nested if statements:<br><br></div> if m := pattern.search(data):<br> ...<br><div><div><div> elif m := other_pattern.search(data):<br> ...<br></div><div> else:<br> ...<br></div><div><br><div>2. Replacing a loop-and-a-half construct:<br><br></div> while m := pattern.search(remaining_data)<wbr>:<br> ...<br><div><div><div><br><div>3. Sharing values between filtering clauses and result expressions in comprehensions:<br><br></div> result = [(x, y, x/y) for x in data if (y := f(x))]<br></div><div><div><div><div><br></div></div></div>The essence of the given clause concept would be to modify *these specific cases* (at least initially) to allow the condition expression to be followed by an inline assignment, of the form "given TARGET = EXPR". (Note: being able to implement such a syntactic constraint is a general
consequence of using a ternary notation rather than a binary one, since
it allows the construct to start with an arbitrary expression, without
requiring that expression to be both the result of the operation *and*
the value bound to a name - it isn't unique to the "given" keyword
specifically)<br><br>While the leading keyword would allow TARGET to be an arbitrary assignment target without much chance for confusion, it could also be restricted to simple names instead (as has been done for PEP 572.<br><br></div><div>With that spelling, the three examples above would become:<br><br></div><div> # Exactly one branch is executed here<br></div><div> if m given m = pattern.search(data):<br> ...<br><div><div><div> elif m given m = other_pattern.search(data)):<br> ...<br></div><div> else:<br> ...<br></div><div><br></div></div></div><div> # This name is rebound on each trip around the loop<br></div><div></div> while m given m = pattern.search(remaining_data)<wbr>:<br> ...<br><div><div><div><br></div></div></div><div><div> # "f(x)" is only evaluated once on each iteration<br></div><div></div> result = [(x, y, x/y) for x in data if y given y = f(x)]</div><div><div><div><div><br></div></div></div></div>Constraining the syntax that way (at least initially) would avoid poking into any dark corners of Python's current scoping and expression execution ordering semantics, while still leaving the door open to later making "result given NAME = expr" a general purpose ternary operator that returns the LHS, while binding the RHS to the given name as a side effect. <br></div><div><div><br></div><div>Using a new keyword (rather than a symbol) would make the new construct easier to identify and search for, but also comes with all the downsides of introducing a new keyword. (Hence the not-entirely-uncommon suggestion of using "with" for a purpose along these lines, which runs into a different set of problems related to trying to use "with" for two distinct and entirely unrelated purposes).<br></div><br></div></div></div>Cheers,<br></div><div>Nick.<span class="HOEnZb"><font color="#888888"><br></font></span></div><span class="HOEnZb"><font color="#888888"><div><div><br>-- <br><div class="m_-5664236774599462832gmail_signature" data-smartmail="gmail_signature">Nick Coghlan | <a href="mailto:ncoghlan@gmail.com" target="_blank">ncoghlan@gmail.com</a> | Brisbane, Australia</div>
</div></div></font></span></div></div></div>
<br>______________________________<wbr>_________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/<wbr>mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/<wbr>codeofconduct/</a><br>
<br></blockquote></div><br><br clear="all"><br>-- <br><div class="gmail_signature" data-smartmail="gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div>
</div>