Tab Atkins Jr. (2014-08-11T19:30:00.000Z)
domenic at domenicdenicola.com (2014-08-18T18:42:13.093Z)
On Mon, Aug 11, 2014 at 11:13 AM, Brendan Eich <brendan at mozilla.org> wrote: > Dave was translating mostly-mechanically from prior source. Yeah, but the result was code that violated common coding guidelines from Python, and so wasn't very illuminating for the question of "what syntax should we use for comprehensions?". > Did you find Peter's comprehensions overlong? I did not, but that's not to > say anything about the original is "easy". It's a great read, especially in > the posted "literate code" form. No, all of Peter's comprehensions are short and easy to comprehend. Comparing it with Dave's version, I think it's simply a matter of the JS comprehensions requiring more syntax, and crossing the line from "easy to read" to "hard to read". Here's the one bit in particular that stands out: Norvig: ```python unitlist = ([cross(rows, c) for c in cols] + [cross(r, cols) for r in rows] + [cross(rs, cs) for rs in ('ABC','DEF','GHI') for cs in ('123','456','789')]) ``` Herman: ```js var unitlist = [for (c of cols) cross(rows, [c])] .concat([for (r of rows) cross([r], cols)]) .concat([for (rs of ["ABC","DEF","GHI"]) for (cs of ["123","456","789"]) cross(rs.split(""), cs.split(""))]); ``` Norvig's is simple and easy to read. Herman's is polluted with additional method calls and more indentation. If we remove the indentation... ```js var unitlist = [for (c of cols) cross(rows, [c])] .concat([for (r of rows) cross([r], cols)]) .concat([for (rs of ["ABC","DEF","GHI"]) for (cs of ["123","456","789"]) cross(rs.split(""), cs.split(""))]); ``` Now pretend that for-of works on strings... (maybe it already does, for all I know, and Dave was just being paranoid) ```js var unitlist = [for (c of cols) cross(rows, c)] .concat([for (r of rows) cross(r, cols)]) .concat([for (rs of ["ABC","DEF","GHI"]) for (cs of ["123","456","789"]) cross(rs, cs)]); ``` Okay, it's still a little bit harder to read, due to the .concat() calls and their attendant additional parens, and the parens around the for-of bodies, but it's not *terribly* worse. It's still bad enough that I don't know if I'd write it. (Man, now that I've looked at these for a bit, I really see the logic of Python putting the value *before* the for. It gives you an examplar value of what the array will look like, right up front, before sliding in the "and here's how you make the rest of them!" indicator. It also means that all three constructions have the cross() call, the important part, lined up in front so you can see the parallel structure more easily. This really helps me comprehend the code, no pun intended.) > Beyond the conciseness, comprehensions should afford engines the ability to > optimize and parallelize. One of the breakthroughs in removing > comprehensions from ES6 was everyone wanting to generalize from 1 (Array) to > N>>1 (iterables, lazy and eager; ParallelArray; other array-likes). > > Rather than adding mappar or pmap, one can use receiver-dispatched methods > polymorphically as in JS funky-OOP today, no need for new delimiters after > [] and () around for/of/if comprehension syntax. We really are out of > delimiters! Oh, I agree with all this. Python's out of delimiters, too, they just happened to have had one more set available, so they could do dict/set comprehensions. They're stuck now as well. ^_^