On Mon, Aug 5, 2013 at 6:26 PM, Mikeal Rogers <[email protected]>wrote:
> > On Aug 5, 2013, at 4:16PM, Jake Verbaten <[email protected]> wrote: > > The only confusion is knowing whether your using generators for async flow > control or whether your using them to generate iterators you iterate over. > Once you learn to only use the first type in synchronous fashion and only > use the second type in an asynchronous fashion the confusion goes away. > > > This is *exactly* what I'm worried about. > > I'm trying to think about this not in the context of "all the code I > write" but "all the code i use, and what they use, and what they use". > > If yield becomes a successful pattern a library user won't be aware of all > the dependent generators it has, just like very few people are aware of > their dependencies dependencies dependencies. Yet somehow all of the actors > along this chain have to be sure they didn't use generators one way when I > want to use them another way. > > This is very concerning. Patterns should enforce or at the very least > visibly display the compatibility they offer so that actors can coordinate > without active collaboration, this sounds like it depends on a bunch of > people all agreeing about how their API should be used without any visible > indicator stating such. > > One of two things will happen: > > * Most iterators will be used for async which means that very few people > will write them in a way that i'm worry about > OR > * Most iterators won't be use for async which means mixing up the two > cases will end in bugs *only* visible at scale. > I'm not sure I understand the concern here. Could you show me a concrete case where this is a problem? Generators are generators. They are not magic. They are also never implicit in ES6. They are annoyingly explicit which has the one good side effect of you will never accidentally get suspended in disinterested code. (I assume this is why they were designed this way) Lets go back to the callback case where sync and async code is mixed: var items = []; array.forEach(function (item) { items.push(item); }); assert.equal(array.length, items.length); In forEach, the callback is *always* synchronous. Or in other words, it will call the callback *before* returning. When it does return, you can know that it's done calling the callback and won't do it ever again. But what if I wrote Stream.prototype.forEach that iterated over a node stream? var items = []; stream.forEach(function (item) { items.push(item); }); assert.equal(items.length, 0); In this case, the forEach function would be async, meaning it *always* calls the callback after it returns. The code block that the assert lives in will run to completion and some later turns of the event loop will trigger the calls to the callback and mutate the shared state `items`. How are generators any worse than this? The only visual queue that state may change at some later time is the function keyword. But *all* functions in javascript use the function keyword. Sync and async. Generators are in an extremely similar boat to callbacks. They are certainly no worse in terms of accidental state clobbering as far as I can tell. They are even more explicit because the only function bodies that are allowed to be suspended are ones marked with `function*`. That star is plenty ugly and hard to miss. I'll bet your dev tools don't even support it and most versions of linters will blow up at this point. Then on top of that, even within these specially marked generator bodies, the only places you can be suspended and resumed are at the `yield` keyword. You can't call a normal function that then yields for you. If you want to delegate this to another function you have to call it using delegating `yield*`, then that function body has to also be marked as a generator body with the star. So the pattern of creating generators that yield promises or continuables and then wrapping in a small helper library that waits for the promise or continuable to resolve is not magic at all. It's extremely explicit. Compare: function insertFile(path, callback) { fs.readFile(path, onFile); function onFile(err, data) { if (err) return callback(err); db.insert(data, callback); } } vs: function insertFile(path, callback) { run(function* () { var data = yield fs.readFile(path); return yield db.insert(data); }, callback); } Both of which are consumed using: insertFile("myfile.txt", function (err, id) { if (err) throw err; console.log("id", id); }); Tell me which is easier to find the two places where your code will be suspended waiting on some I/O to complete? I have been playing with these techniques for years now and while there are dangers in some systems (like node's original promise.wait, lua's coroutines, or node-fibers), the danger about accidental suspension does not exist with es6 generators! If there is something I'm missing, please show it to me. I've been wrong before on this list. ( https://groups.google.com/d/msg/nodejs/eK00eDF-4Zw/FQhDrlEs0xUJ) -Tim Caswell > > -Mikeal > > -- > -- > Job Board: http://jobs.nodejs.org/ > Posting guidelines: > https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines > You received this message because you are subscribed to the Google > Groups "nodejs" group. > To post to this group, send email to [email protected] > To unsubscribe from this group, send email to > [email protected] > For more options, visit this group at > http://groups.google.com/group/nodejs?hl=en?hl=en > > --- > You received this message because you are subscribed to the Google Groups > "nodejs" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > For more options, visit https://groups.google.com/groups/opt_out. > > > -- -- Job Board: http://jobs.nodejs.org/ Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines You received this message because you are subscribed to the Google Groups "nodejs" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/nodejs?hl=en?hl=en --- You received this message because you are subscribed to the Google Groups "nodejs" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/groups/opt_out.
