<div dir="ltr"><div class="gmail_quote"><div dir="ltr">On Fri, Jun 22, 2018 at 10:19 AM Chris Angelico <<a href="mailto:rosuav@gmail.com">rosuav@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Sat, Jun 23, 2018 at 3:02 AM, Michael Selik <<a href="mailto:mike@selik.org" target="_blank">mike@selik.org</a>> wrote:<br>
> On Fri, Jun 22, 2018 at 8:09 AM Antoine Pitrou <<a href="mailto:solipsis@pitrou.net" target="_blank">solipsis@pitrou.net</a>> wrote:<br>
>><br>
>> Thank you.  Personally, I'd like to see feedback from<br>
>> educators/teachers after they take the time to read the PEP and take<br>
>> some time to think about its consequences.<br>
><br>
><br>
> I've started testing the proposed syntax when I teach. I don't have a large<br>
> sample yet, but most students either dislike it or don't appreciate the<br>
> benefits. They state a clear preference for shorter, simpler lines at the<br>
> consequence of more lines of code.<br>
<br>
This is partly because students, lacking the experience to instantly<br>
recognize larger constructs, prefer a more concrete approach to<br>
coding. "Good code" is code where the concrete behaviour is more<br>
easily understood. As a programmer gains experience, s/he learns to<br>
grok more complex expressions, and is then better able to make use of<br>
the more expressive constructs such as list comprehensions.<br></blockquote><div><br></div><div>I don't think that's the only dynamic going on here. List comprehensions are more expressive, but also more declarative and in Python they have nice parallels with SQL and speech patterns in natural language. The concept of a comprehension is separate from its particular expression in Python. For example, Mozilla's array comprehensions in Javascript are/were ugly [0].</div><div><br></div><div>Students who are completely new to programming can see the similarity of list comprehensions to spoken language. They also appreciate the revision of certain 3-line and 4-line for-loops to comprehensions. I didn't get the same sense of "Oh! That looks better!" from my students when revising code with an assignment expression.</div><div><br></div><div>Despite my best efforts to cheerlead, some students initially dislike list comprehensions. However, they come around to the idea that there's a tradeoff between line density and code block density. Comprehensions have a 3-to-1 or 4-to-1 ratio of code line shrinkage. They're also often used in sequence, like piping data through a series of transforms. Even if students dislike a single comprehension, they agree that turning 15 lines into 5 lines improves the readability.</div><div><br></div><div>In contrast, an assignment expression only has a 2-to-1 code line compression ratio. It might save a level of indentation, but I think there are usually alternatives. Also, the assignment expression is less likely to be used several times in the same block.</div><div><br></div><div>A good pitch for an assignment expression is refactoring a cascade of regular expressions:</div><div><br></div><div><br></div><div><div>    for line in f:</div><div>        mo = foo_re.search(line)</div><div>        if mo is not None:</div><div>            foo(mo.groups())</div><div>            continue</div><div><br></div><div>        mo = bar_re.search(line)</div><div>        if mo is not None:</div><div>            bar(mo.groups())</div><div>            continue</div><div><br></div><div>        mo = baz_re.search(line)</div><div>        if mo is not None:</div><div>            baz(mo.groups())</div><div>            continue</div><div><br></div><div><br></div><div>Here the assignment operator makes a clear improvement:</div><div><br></div><div>    for line in f:</div><div>        if (mo := foo_re.search(line)) is not None:</div><div>            foo(mo.groups())</div><div>        elif (mo := bar_re.search(line)) is not None:</div><div>            bar(mo.groups())</div><div>        elif (mo := baz_re.search(line)) is not None:</div><div>            baz(mo.groups())</div></div><div><br></div><div><br></div><div>However, I think this example is cheating a bit. While I've written similar code many times, it's almost never just a function call in each if-block. It's nearly always a handful of lines of logic which I wouldn't want to cut out into a separate function. The refactor is misleading, because I'd nearly always make a visual separation with a newline and the code would still look similar to the initial example.</div><div><br></div><div><br></div><div>[0] <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Array_comprehensions">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Array_comprehensions</a></div></div></div>