Introduction, comprehensions beyond arrays

Mike Stay metaweta at gmail.com
Sat May 11 13:32:54 PDT 2013


I keep forgetting to hit "Reply to all", sorry.

On Fri, May 10, 2013 at 2:34 PM, Brendan Eich <brendan at mozilla.com> wrote:
> So, just to be clear, now the issue isn't that comprehensions make arrays,
> it's that iteration isn't X. What is X? Quiz rule: don't say "Monad" or
> "Monadic" in your answer. :-|

Actually, if we could provide a different flatten operation, that
would suffice, since the iterator could simply provide a single value
of the appropriate class.  For example, given an iterator that
produced integers, we could do matrix multiplication if flatten summed
all the elements of the inner lists instead of concatenating the inner
lists.

If
   [for (x of foo) for (y of bar(x)) for (z of baz(x,y)) expr(x, y, z)]
iterated as usual over foo, bar(x) and baz(x,y) but used the flatten()
method of bar(x) on the innermost list of lists and the flatten()
method of foo on the outermost list of lists, that would do everything
I was hoping for.

In particular, the expression

[ for (w of obj)
  for (x of foo(w))
  for (y of bar(w,x))
  for (z of baz(w,x,y))
  if (cond(w,x,y,z))
  expr(w,x,y,z)
]

would translate as

let resultObj = [];
let onceObj = obj;
for (let w of onceObj) {
    let resultFoo = [];
    let onceFoo = foo(w);
    for (let x of onceFoo) {
        let resultBar = [];
        let onceBar = bar(w,x);
        for (let y of onceBar) {
            let resultBaz = [];
            let onceBaz = baz(w,x,y);
            for (let z of onceBaz) {
                if (cond(w,x,y,z)) {
                    resultBaz.push(expr(w,x,y,z));
                }
            }
            resultBar.push(resultBaz);
        }
        resultBar = (onceBar.flatten || [].flatten).call(resultBar);
        resultFoo.push(resultBar);
    }
    resultFoo = (onceFoo.flatten || [].flatten).call(resultFoo);
    resultObj.push(resultFoo);
}
resultObj = (onceObj.flatten || [].flatten).call(resultObj);

No change to the syntax, no change to the iterator semantics, and a
compatible change to the flattening semantics (assuming the existence
of Array.prototype.flatten).


P.S. For those who do like monads, instead of binding functions of
type A->TB and B->TC, we'd just be binding functions of type A->[TB]
and B->[TC].
-- 
Mike Stay - metaweta at gmail.com
http://www.cs.auckland.ac.nz/~mike
http://reperiendi.wordpress.com


More information about the es-discuss mailing list