Andy Wingo (2014-08-11T13:49:05.000Z)
domenic at domenicdenicola.com (2014-08-18T18:38:23.640Z)
I can give it a go ;) We can start with generator comprehensions, which are a specific way of constructing lazy sequences. It's a syntactic feature, which has a cost on the language level -- makes you wonder, can this be done without syntax? Turns out, yes: you can do it by constructing a graph of combinators, with normal method syntax. So you can do: ```js var sequence = iterable.lazy().if(somePredicate) ``` where lazy and if might be: ```js Iterable.prototype.lazy = function* () { for (var x of this) yield x; } Iterable.prototype.if = function* (pred) { for (var x of this) if pred(x) yield x; } ``` The neat thing about this is that it's extensible -- it privileges the users to the same degree as the language designers. If there's a new pipeline-like operator, it can be polyfilled on Iterator.prototype. It also allows for look-alike APIs for other kinds of traversal: for example, the same syntax could map over parallel arrays in parallel. There is also an argument that a more combinator-like syntax can better support pushing values into iterators, a concept described as "Observables" rather than "Iterables", but I don't remember the details and can't describe it adequately. The end point of all these arguments is that a more combinator-like, linq-like API is as expressive and more extensible than a hard-coded syntactic facility. I love _array_ comprehensions -- they are light-weight both from a performance and syntactic point of view. You can quickly build up short arrays, and at least in SpiderMonkey you get a lovely ionified loop. Generator comprehensions were unlikely to be as light-weight from a perf perspective, but the use of () instead of [] was a cute pun, and could have gently pushed people in the lazy direction. But then, if combinators are better for the lazy case, then the case for eager traversal is less strong -- and so we end up in current situation of punting on both of them for now. In many ways it's too bad -- Array.map is usually much worse than a for-of and Array.push, which is what an array comprehension is, and using combinators means you can't yield in the comprehended expression (`[for (x of y) ... yield ...]`). But the extensibility benefit of combinators on Iterator.prototype will probably make deferal of comprehensions a net win for many programmers.