<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Fri, 4 May 2018 at 05:07 Nick Coghlan <<a href="mailto:ncoghlan@gmail.com">ncoghlan@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><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):<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):<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></div></div></div></blockquote><div><br></div><div>My brain wants to drop the variable name in front of 'given':<br><br></div><div>if given m = pattern.search(data):<br><br></div><div>while given m = pattern.search(remaining_data):<br><br></div><div>Maybe it's because the examples use such a short variable name?<br><br></div><div>if match given match = pattern.search(data):<br></div><div>vs.<br></div><div>if given match = pattern.search(data);<br><br></div><div>Nope, I still like mine more. ;)<br><br></div><div>-Brett<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div><div><div><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.<br></div><div><div><br>-- <br><div class="m_-2751348143358262123gmail_signature" data-smartmail="gmail_signature">Nick Coghlan   |   <a href="mailto:ncoghlan@gmail.com" target="_blank">ncoghlan@gmail.com</a>   |   Brisbane, Australia</div>
</div></div></div></div></div>
_______________________________________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org" target="_blank">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/codeofconduct/</a><br>
</blockquote></div></div>