Hacker News new | ask | show | jobs
by pyrtsa 4824 days ago
I asked the same question in Twitter. Turns out James was actually augmenting (i.e. modifying) the array object `promises` to behave as a promise itself. I don't think this was a particularly beautiful way of doing it but it seems to work now that I think of it.

Promise libraries, like RSVP.js [1] he referred to, typically implement a way to construct a promise with a depends-on-many relationship, as a function possibly called `all([p1, p2, ...])` (with the same type signature as for `list`), `and(p1, p2, ...)` or something similar.

IMO, defining the `list` function that way would've been clearer to the reader and more FP'ish, treating the `promises` argument in as a value and not a mutable object.

[1]: https://github.com/tildeio/rsvp.js/blob/master/lib/rsvp/all....

1 comments

A day later I looked at this again and I'm a little closer to understanding.

      var listPromise = new Promise();
creates an object that, being a Promise object, has certain methods and internal state, derived from the prototype of Promise.

      for (var k in listPromise) promises[k] = listPromise[k];
This confused me because I thought "k" was a stand-in for a numeric index, e.g. that it was doing promises[0] = listPromise[0], promises[1] = listPromise[1], etc. That is not what's going on. Rather, "k" refers to attributes and/or methods that objects of the Promise class have by default. It's copying those onto `promises` — the array `promises` itself, not the individual items `promises[i]`, which keep their existing methods and attributes.

Coming from a Python background, I think I would have found this more obvious if the variable "k" were instead called "method" or "attr". If it was `for (var method in listPromise)` it'd be much clearer what's going on, whereas single-letter variables like i, j, and k are, to me, stand-ins for integers.

It was also confusing, as you said, that the function uses destructive update rather than treating the input as a value. James did mention this ("augmenting the list with promise methods"), but it's still unexpected, especially when the function is preceded by a Haskell type signature.

The reason I only say I'm closer to understanding, and not quite there yet, is I'm not sure what it means to do `new Promise()` or what is being copied over in the above for-loop. I tried James's code with a Promises/A+ implementation, rsvp.js (https://github.com/tildeio/rsvp.js), but it won't let me do `new Promise()` because it works differently:

    > var promise = new RSVP.Promise();
    TypeError: You must pass a resolver function as the sole argument to the promise constructor
Per an example in RSVP.js's readme, it's expecting this:

    var promise = new RSVP.Promise(function(resolve, reject){
        // set up a callback that calls either resolve(...)
        // or reject(...)
    });
If James is using a specific promises implementation in his code, it appears to be the one he defined in a past blog post (http://blog.jcoglan.com/2011/03/11/promises-are-the-monad-of...), which in turn builds on a module from his JS.Class library (http://jsclass.jcoglan.com/deferrable.html), which I hadn't heard of before.

I still think this is a great article, but that code snippet has proven to be quite a puzzle.