<div style="line-height:1.7;color:#000000;font-size:14px;font-family:Arial"><div style="line-height:1.7;color:#000000;font-size:14px;font-family:Arial">Thanks so much for the comments and the collect on this syntax!<br><br>Comments on *previous talk*<br>The list also mentioned some other previous proposals, so I myself search it and find that there're even more in the mailing list since 2008.<br>https://mail.python.org/pipermail/python-ideas/2008-August/001842.html<br><br>Comments on *previous talk: PEP*<br>The PEP seems to be about an explicit temporary namespace where any objects (including functions, classes, etc.) could be held.<br>However, I find that this syntax may not work for temporary variables in comprehensions.<br><br>We might expect this syntax work like<br>[?.y+2 for x in range(5) given: y = x+1]<br>But notice that the proposed `given` statement here appeared in comprehensions, where syntax changes in comprehensions are needed, and nothing about this is mentioned in the PEP.<br>What's more, the proposed syntax is a statement like `for` statement, `if` statement, rather than a for-clause or if-clause in comprehensions. In my opinion, it's not a good idea to have a statement in comprehensions. Instead, another given-clause should be added if one wants to write code like above, doing assignments in comprehensions, which can look like:<br>[?.y+2 for x in range(5) given y = x+1]<br>So the ? symbol seems useless here, so maybe<br>[y+2 for x in range(5) given y = x+1]<br>make it quite similar to the `where` syntax you proposed.<br><br>So, I agree with you that it is a good idea to have a new PEP, though for a different reason.<br> <br>Comments on *Choice of syntax*<br>I gave two candidate syntaxs in https://mail.python.org/pipermail/python-ideas/2008-August/001842.html, one said `for ... in ...`, another said `with ... as ...`.<br>The first has the same problem as `for ... = ...` you proposed. And the biggest problem I think the second will face is the difference in semantic between the `with` statement and it.<br>When it comes to `where ... = ...`, there are one possible problem I can think of.<br>`where` is not now a keyword in Python. There are WHERE clauses in SQL, so in many modules including peewee and SQLAlchemy, `where` is an important method. The new syntax would cause quite incompatibilities.<br><br>Personally I agreed with you that postfix notation would have advantage over prefix notation. Other than `where`, `with` is quite readable in my opinion. So maybe `with ... = ...` can be another candidate?<br><br>Plus the `given ... = ...` I mentioned above, there are several more candidates now. Personally I perfer `with ... = ...`, because `with` is a python keyword so it would be good for backward compatibility.<br><br>*About comprehensions and expressions*<br>You gave `print(y+2 where y = x+1)` as an example, I think it should be clarified that it's not, or at least, does not look like a comprehension, but an expression. It should give an object `y+2` rather than a list or a generator. (otherwise what list can it give?)<br>There are for-clause and if-clause for comprehensions, and if-clause (aka ternary operators) for expressions. So, In my opinion, there should be additional discuss and examples to show that it's helpful to have such syntax.<br><br>For the where-clause in expressions, I think we could refer to how python handles if-clause.<br>The following setences are legal:<br>[x if x else 0 for x in mylist if x > 10]<br>The following illegal:<br>[x if x for x in mylist if x > 10]<br>[x if x else 0 for x in mylist if x > 10 else 10]<br>That's to say, the two kinds of if-clause, one is only used in expressions (aka `ternary operator`), the other is only used in comprehensions. They slightly differ in syntax.<br><br>The where-clause might work in similar ways. Then<br>[z+2 where z = y+1 for x in mylist where y = x+1]<br>means<br>[(z+2 where z=y+1) for x in mylist where y = x+1]<br>where the parenthesis (also the part before the first `for`) is a expression, the rest is comprehension clauses.<br>To be more accurate, the new syntax would be:<br><br>test: where_test ['if' where_test 'else' test] | lambdef<br>where_test: or_test | ( '(' or_test 'where' NAME '=' testlist_star_expr ')' )<br><br>Mandatory parenthesis in where_test is to resolve the ambiguity in code like<br>print(y+2 where y=x+1 if x>0 else x-1 if x>1 else 0)<br>It could be analysed like<br>print((y+2 where y=x+1 if x>0 else x-1) if x>1 else 0)<br>or <br>print(y+2 where y=(x+1 if x>0 else x-1 if x>1 else 0)).<br>I guess thektulu may have mandatory parenthesis for the same reason.<br><br>I haven't check the new syntax very carefully so there might be other ambiguities.<br><br>Another example is<br>print(y+2 if x>0 else y-2 where y=x+1)<br>with mandatory parenthesis, one must write<br>print((y+2 if x>0 else y-2 where y=x+1))<br>or<br>print(y+2 if x>0 else (y-2 where y=x+1))<br><br>However, it might still confuse many people. I wonder whether it's a good idea to have such syntax.<br><br>It would be much easier to add assignments in comprehensions.<br>comp_iter: comp_for | comp_if | comp_where<br>comp_where: 'where' NAME '=' testlist_star_expr [comp_iter]<br><br>Comments on *Goals of the new syntax*<br>I have a real-world example in https://mail.python.org/pipermail/python-ideas/2018-February/048997.html, it's to generate a big json, you seem to have a very goods feeling of it though you didn't give a real-world example.<br><br><br><br><br><div style="position:relative;zoom:1"></div><div id="divNeteaseMailCard"></div><br>At 2018-02-16 12:03:23, "Robert Vanden Eynde" <<a href="mailto:robertve92@gmail.com">robertve92@gmail.com</a>> wrote:<br> <blockquote id="isReplyContent" style="PADDING-LEFT: 1ex; MARGIN: 0px 0px 0px 0.8ex; BORDER-LEFT: #ccc 1px solid"><div dir="auto">Hello, talking about this syntax :<div dir="auto"><br></div><div dir="auto">[y+2 for x in range(5) let y = x+1]<br><div dir="auto"><br></div><div dir="auto">*Previous talks*</div><div dir="auto">I've had almost exactly the same idea in June 2017, see subject "variable assignment in functional context here: <a href="https://mail.python.org/pipermail/python-ideas/2017-June/subject.html" target="_blank">https://mail.python.org/<wbr></wbr>pipermail/python-ideas/2017-<wbr></wbr>June/subject.html</a>.<div dir="auto"><br></div><div dir="auto">Currently this can easily be done by iterating over a list of size 1:</div><div dir="auto"><br></div><div dir="auto">[y+2 for x in range(5) for y in [x+1]]</div><div dir="auto"><br></div><div dir="auto">(Other ways exist, see section "current possibilities" below).</div><div dir="auto"><br></div><div dir="auto">This comparison would answer a lot of questions like "can we write [x+2 for x in range(5) for x in [x+1]], so [x+2 for x in range(5) let x = x+1]" the new variable would indeed shadow the old one.</div><div dir="auto"><br></div><div dir="auto">In June 2017 I introduced the "let" syntax using the existing "for" keyword, using the "=" instead of a "in" like this:</div><div dir="auto"><br></div><div dir="auto"><span style="font-family:sans-serif">[y+2 for x in range(5) for y = x+1]</span></div><div dir="auto"><br></div><div dir="auto">The only difference I introduced was that it would be logical to accept the syntax in any expression:</div><div dir="auto"><br></div><div dir="auto">x = 5</div><div dir="auto">print(y+2 for y = x + 1)</div><div dir="auto"><br></div><div dir="auto">or with the "let" keyword:</div><div dir="auto"><br></div><div dir="auto">x = 5</div><div dir="auto">print(y+2 let y = x + 1)</div><div dir="auto"><br></div><div dir="auto">*Previous talk: Pep*</div><div dir="auto">In the June conversation one conclusion was that someone wrote a pep (<a href="https://www.python.org/dev/peps/pep-3150/" target="_blank">https://www.python.org/dev/<wbr></wbr>peps/pep-3150/</a>) in 2010 that's still pending (not exactly the same syntax but the same idea, he used a "given:" syntax) that looked like that :</div><div dir="auto"><br></div><div dir="auto">print(y+2 given:</div><div dir="auto">            y=x+1)</div><div dir="auto"><br></div><div dir="auto">*Previous talk: GitHub implementation on Cython*</div><div dir="auto">Another conclusion was that someone on GitHub implemented a "where" statement in Cython (url: <a href="https://github.com/thektulu/cpython/commit/9e669d63d292a639eb6ba2ecea3ed2c0c23f2636" target="_blank">https://github.com/thektulu/<wbr></wbr>cpython/commit/<wbr></wbr>9e669d63d292a639eb6ba2ecea3ed2<wbr></wbr>c0c23f2636</a>) where one could write :</div><div dir="auto"><br></div><div dir="auto">print(y+2 where y = x+1)</div><div dir="auto"><br></div><div dir="auto">So in a list comprehension:</div><div dir="auto"><br></div><div dir="auto">[y+2 where y = x + 1 for x in range(5)]</div><div dir="auto"><br></div><div dir="auto">As the author thektulu said "just compile and have fun".</div><div dir="auto"><br></div><div dir="auto">*New syntax in list comprehension*</div><div dir="auto">However, we probably would like to be able to use this "where" after the for:</div><div dir="auto"><br></div><div dir="auto">[y+2 for x in range(5) where y = x+1]</div><div dir="auto"><br></div><div dir="auto">This would allow the new variable to be used in further "for" and "if" statement :</div><div dir="auto"><br></div><div dir="auto"><span style="font-family:sans-serif">[y+z for x in range(5) where y = x+1 for z in range(y+1)]</span><br></div><div dir="auto"><br></div><div dir="auto">*Choice of syntax*</div><div dir="auto">Initially I thought re-using the "for" keyword would be a good idea for backward comptability (a variable named "where" in old code wouldn't be a problem), however some people pointed out that the python Grammar wouldn't be LL1, when reading the "for" token it wouldn't be able to choose directly if the rest would be a "for in" or "for =" so actually introducing a dedicated keyword is probably better, like this :</div><div dir="auto"><br></div><div dir="auto">[y+2 for x in range(5) where y = x+1]</div><div dir="auto"><span style="font-family:sans-serif">print(y+2 where y = x+1)</span><br></div><div dir="auto"><br></div><div dir="auto">The "where" keyword is very readable in my opinion, very close to English sentences we use. Sometimes we introduce a new variable before using it, generally using "let" or after using it using "where". For example "let y = x+1; print(y+2)". Or "print(y+2 where y = x+1)".</div><div dir="auto"><br></div><div dir="auto">The first syntax is chosen in the "let in" syntax in haskell :</div><div dir="auto"><br></div><div dir="auto"><div dir="auto" style="font-family:sans-serif">print(let y = x+2 in y+2)</div><div dir="auto" style="font-family:sans-serif"><br></div><div dir="auto" style="font-family:sans-serif">Or chained:</div><div dir="auto" style="font-family:sans-serif">print(let x = 2 in let y = x+1 in y+2)</div><div dir="auto" style="font-family:sans-serif"><br></div><div dir="auto" style="font-family:sans-serif">But Haskell user would probably line break for clarity :</div><div dir="auto" style="font-family:sans-serif"><br></div><div dir="auto" style="font-family:sans-serif">print(let x = 2 in</div><div dir="auto" style="font-family:sans-serif">         let y = x+1 in</div><div dir="auto" style="font-family:sans-serif">         y+2)<br></div><div dir="auto" style="font-family:sans-serif"><br></div><div dir="auto" style="font-family:sans-serif">A postfix notation using "where" would probably be less verbose in my opinion. Another example of "postfix notation" python has is with the "a if condition else b" so adding a new one wouldn't be surprising. Furthermore, the postfix notation is preferred in the context of "presenting the result first, then the implementation" (context discussed already in the 2010 pep), the "presenting the result first" is also a goal of the list comprehension, indeed one does write [x+3 for x in range(5)] and not [for x in range(5): x+3], the latter would be more "imperative programming" style, and would be translated to a normal loop.</div></div><div dir="auto"><br></div><div dir="auto">The problem of chaining without parenthesis, how to remove the parenthesis in the following statement ?</div><div dir="auto"><br></div><div dir="auto">print((y+2 where y = x+1) where x = 2)</div><div dir="auto"><br></div><div dir="auto">We have two options :</div><div dir="auto"><br></div><div dir="auto">print(y+2 where x = 2 where y = x+1)</div><div dir="auto"><div dir="auto" style="font-family:sans-serif">print(y+2 where y = x+1 where x = 2)</div><div dir="auto" style="font-family:sans-serif"><br></div><div dir="auto" style="font-family:sans-serif">The first option would be probably closer to the way multiple "for" are linked in a list comprehension:</div><div dir="auto" style="font-family:sans-serif"><br></div><div dir="auto" style="font-family:sans-serif">[y+2 for x in range(5) for y in [x+1]]</div><div dir="auto" style="font-family:sans-serif"><br></div><div dir="auto" style="font-family:sans-serif">But the second option would be more "present result first" and more close to the parenthesized version, the user would create new variables as they go, "I want to compute y+2 but hey, what is y ? It's x+1 ! But what is x ? It's 5 !)). However, keeping the same order as in "multiple for in list comprehension" is better, so I'd choose first option.</div></div><div dir="auto"><br></div><div dir="auto">In the implementation on GitHub of thektulu the parenthesis are mandatory.</div><div dir="auto"><br></div><div dir="auto">Another syntax issue would probably surprise some users, the following statement, parenthesized :</div><div dir="auto"><br></div><div dir="auto">[(y+2 where y = x+1) for x in range(5)]</div><div dir="auto"><br></div><div dir="auto">Would have two totally legal ways to be done:</div><div dir="auto"><br></div><div dir="auto">[y+2 where y = x+1 for x in range(5)]</div><div dir="auto">[y+2 for x in range(5) where y = x+1]</div><div dir="auto"><br></div><div dir="auto">The first one is a consequence of the "where" keyword usable in an expression and the second one is a consequence of using it in a list comprehension.</div><div dir="auto"><br></div><div dir="auto">However I think it doesn't break the "there is only one obvious way to do it", because depending on the case, the "y" variable would be a consequence of the iteration or a consequence of the computation.</div><div dir="auto"><br></div><div dir="auto">*Goals of the new syntax*</div><div dir="auto">Personally, I find it very useful to do an assignment in such context, I use list comprehension for example to generate a big json with multiple for and if.</div><div dir="auto"><br></div><div dir="auto">I don't have here a list of big real world example thar would be simplified using this syntax but people interested could search arguments here.</div><div dir="auto"><br></div><div dir="auto">People could argue only the "list comprehension" case would be useful and not the "any expression" case:</div><div dir="auto"><br></div><div dir="auto">[y+2 for x in range(5) where y = x+1]</div><div dir="auto">would be accepted but not :</div><div dir="auto"><br></div><div dir="auto">print(y+2 where y=x+1)</div><div dir="auto"><br></div><div dir="auto">Because the latter could be written:</div><div dir="auto"><br></div><div dir="auto">y = x + 1</div><div dir="auto">print(y+2)</div><div dir="auto"><br></div><div dir="auto">However, the idea of having an isolated scope can be a good idea.</div><div dir="auto"><br></div><div dir="auto">*Current possibilities*</div><div dir="auto">Currently we have multiple options :</div><div dir="auto"><br></div><div dir="auto">[y+2 for x in range(5) for y in [x+1]]</div><div dir="auto">[y+2 for (x+1 for x in range(5))]</div><div dir="auto">[(lambda y:y+2)(y=x+1) for x in range(5)]</div><div dir="auto"><br></div><div dir="auto">The first one works well but it's not obvious we just want to assign a new variable, especially when the expression is long, or multiple, or both:</div><div dir="auto">[y+z for x in range(5) for y,z in [((x + 1) * 2, x ** 2 - 5)]]</div><div dir="auto"><br></div><div dir="auto">The second one makes it impossible to reuse the "x" variable and the y = x+1 relation is not obvious.</div><div dir="auto"><br></div><div dir="auto">The third example is what a functional programmer would think but is really too much complex for a beginner and very verbose.</div><div dir="auto"><br></div><div dir="auto">*Proposed syntax : Conclusion*</div><div dir="auto">As I said, I like the "where" syntax with the "where" keyword.</div><div dir="auto"><br></div><div dir="auto">[y+2 for x in range(5) where y = x+1]</div><div dir="auto"><br></div><div dir="auto">Also usable in any expression :</div><div dir="auto"><br></div><div dir="auto">print(y+2 where y = x+1)</div><div dir="auto"><br></div><div dir="auto">*Conclusion*</div><div dir="auto"><br></div><div dir="auto">Here is all the talk/work/argument I've already found about this syntax. Apparently it's been a while (2010) since such an idea was thought but I think having a new pep listing all the pros and cons would be a good idea. So that we can measure how much the community would want this concept to be introduced, and if it's refused, the community would have a document where the "cons" are clearly written.</div><div dir="auto"><br></div><div dir="auto">Robert Vanden Eynde</div></div></div></div>
</blockquote></div></div><br><br><span title="neteasefooter"><p> </p></span>