5 ms·
This code doesn't look right to me: // list :: [Promise a] -> Promise [a] var list = function(promises) { var listPromise = new Promise();
by graue 14y ago
This code doesn't look right to me:
// list :: [Promise a] -> Promise [a]
var list = function(promises) {
var listPromise = new Promise();
for (var k in listPromise) promises[k] = listPromise[k];
Perhaps the assignment is supposed to be the other way around?
for (var k in promises) listPromise[k] = promises[k];
- aethertap 14y agoI agree, I was going to ask the same question. Unless there's some subtlety that I'm missing, the order you propose makes much more sense.
- ams6110 14y agoI'm glad someone else thought that looked odd.
- pyrtsa 14y agoI 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.js https://github.com/tildeio/rsvp.js/blob/master/lib/rsvp/all....
- graue 14y agoA 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 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-asynchronous-programming/ 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 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.