<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 5 May 2018 at 13:36, Tim Peters <span dir="ltr"><<a href="mailto:tim.peters@gmail.com" target="_blank">tim.peters@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">[Nick Coghlan <<a href="mailto:ncoghlan@gmail.com">ncoghlan@gmail.com</a>>]<br>
> ...<br>
<span class="">> The essence of the given clause concept would be to modify *these specific<br>
> cases* (at least initially) to allow the condition expression to be followed<br>
> by an inline assignment, of the form "given TARGET = EXPR".<br>
<br>
</span>I'm not clear on what "these specific cases" are, specifically ;-)<br>
Conditions in "if", "elif", and "while" statement expressions?<br></blockquote><div><br></div><div>Exactly the 3 cases presented (if/elif/while conditions). The usage in comprehensions would mirror the usage in if statements, and avoid allowing name bindings in arbitrary locations due to the implicity nested scopes used by comprehensions.<br><br>Conditional expressions would be initially omitted since including them would allow arbitrary name bindings in arbitrary locations via the quirky "x if x given x = expr else x" spelling, and because "else" isn't as distinctive an ending token as "given ... :", "given ... )", "given ... ]", or "given ... }".<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Restricted to one "given" clause, or can they chain?  In a listcomp,<br>
is it one "given" clause per "if", or after at most one "if"?  Or is<br>
an "if" even needed at all in a listcomp?  For example,<br>
<br>
    [(f(x)**2, f(x)**3) for x in xs]<br>
<br>
has no conditions, and<br>
<br>
    [(fx := f(x))**2, fx**3) for x in xs]<br>
<br>
is one reasonable use for binding expressions.<br>
<br>
    [(fx**2, fx**3) for x in xs given fx = f(x)]<br>
<br>
reads better, although it's initially surprising (to my eyes) to find<br>
fx defined "at the end".  But no more surprising than the current:<br>
<br>
    [(fx**2, fx**3) for x in xs for fx in [f(x)]]<br>
<br>
trick.<br>
<br></blockquote><div><br></div><div>There were a couple key reasons I left the "for x in y" case out of the initial proposal:<br><br></div><div>1. The "for x in y" header is already quite busy, especially when tuple unpacking is used in the assignment target<br></div><div>2. Putting the "given" clause at the end would make it ambiguous as to whether it's executed once when setting up the iterator, or on every iteration<br></div><div>3. You can stick in an explicit "if True" if you don't need the given variable in the filter condition<br></div><div><br>    [(fx**2, fx**3) for x in xs if True given fx = f(x)]<br><br></div><div>And then once you've had an entire release where the filter condition was mandatory for the comprehension form, allowing the "if True" in "[(fx**2, fx**3) for x in xs given fx = f(x)]" to be implicit would be less ambiguous.<br></div><div></div><div><br></div><div>[snip]<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

It''s certain sanest as<br>
<br>
    if x**2 + y**2 > 9 given x, y = func_returning_twople():<br>
<br>
"given" really shines there!<br></blockquote><div><br></div><div>Yep, that's why I don't have the same immediate reaction of "It would need to be limited to simple names as targets" reaction as I do for assignment expressions. It might still be a good restriction to start out with, though (especially if we wanted to allow multiple name bindings in a single given clause).<br></div><div><br></div><div>[snip]<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
The one-letter variable name obscures that it doesn't<br>
actually reduce _redundancy_, though.  That is, in the current<br>
<br>
    match = pattern.search(data)<br>
    if match:<br>
<br>
it's obviously less redundant typing as:<br>
<br>
    if match := pattern.search(data):<br>
<br>
In<br>
<br>
    if match given match = pattern.search(data):<br>
<br>
the annoying visual redundancy (& typing) persists.<br></blockquote><div><br></div><div>Right, but that's specific to the case where the desired condition really is just "bool(target)". That's certainly likely to be a *common* use case, but if we decide that it's *that* particular flavour of redundancy that really bothers us, then there's always the "if expr as name:" spelling (similar to the way that Python had "a and b" and "a or b" logical control flow operators long before it got "a if c else b").<br></div><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
One more, a lovely (to my eyes) binding expression simplification<br>
requiring two bindings in an `if` test, taken from real-life code I<br>
happened to write during the PEP discussion:<br>
<br>
    diff = x - x_base<br>
    if diff:<br>
        g = gcd(diff, n)<br>
        if g > 1:<br>
            return g<br>
<br>
collapsed to the crisp & clear:<br>
<br>
    if (diff := x - x_base) and (g := gcd(diff, n)) > 1:<br>
        return g<br>
<br>
If only one trailing "given" clause can be given per `if` test<br>
expression, presumably I couldn't do that without trickery.</blockquote><div><br></div><div>I was actually thinking that if we did want to allow multiple assignments, and we limited targets to single names, we could just use a comma as a separator:<br><br>    if diff and g > 1 given diff = x - x_base, g = gcd(diff, n):<br>
        return g<br><br></div><div>Similar to import statements, optional parentheses could be included in the grammar, allowing the name bindings to be split across multiple lines:<br><br>    if diff and g > 1 given (<br>        diff = x - x_base,<br>        g = gcd(diff, n),<br>    ):<br>
        return g<br></div><div>
<br></div><div>(Other potential separators would be ";", but that reads weirdly to me since my brain expects the semi-colon to end the entire statement, and "and", but that feels overly verbose, while also being overly different from its regular meaning)<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">  If it's<br>
more general,<br>
<br>
    if (diff given diff = x _ xbase) and g > 1 given g = gcd(diff, n):<br>
<br>
reads worse to my eyes (perhaps because of the "visual redundancy"<br>
thing again), while<br>
<br>
   if diff and g > 1 given diff = x - x_base given g = gcd(diff, n):<br>
<br>
has my eyes darting all over the place, and wondering which of the<br>
trailing `given` clauses executes first.<br></blockquote><div><br></div></div>I find that last effect is lessened when using the comma as a separator within the given clause rather than repeating the keyword itself.<br><br></div><div class="gmail_extra">Cheers,<br></div><div class="gmail_extra">Nick.<br clear="all"></div><div class="gmail_extra"><br>-- <br><div class="gmail_signature" data-smartmail="gmail_signature">Nick Coghlan   |   <a href="mailto:ncoghlan@gmail.com" target="_blank">ncoghlan@gmail.com</a>   |   Brisbane, Australia</div>
</div></div>