On Tue, Aug 6, 2013 at 12:00 PM, Tim Caswell <t...@creationix.com> wrote:

>
>
>
> On Mon, Aug 5, 2013 at 6:26 PM, Mikeal Rogers <mikeal.rog...@gmail.com>wrote:
>
>>
>> On Aug 5, 2013, at 4:16PM, Jake Verbaten <rayn...@gmail.com> 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.
>

Just wanted to interject some good news here: JSHint has already been
updated with support for generator functions, by setting the es6 flag to
`true` :)

Rick





> 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 nodejs@googlegroups.com
>> To unsubscribe from this group, send email to
>> nodejs+unsubscr...@googlegroups.com
>> 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 nodejs+unsubscr...@googlegroups.com.
>> 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 nodejs@googlegroups.com
> To unsubscribe from this group, send email to
> nodejs+unsubscr...@googlegroups.com
> 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 nodejs+unsubscr...@googlegroups.com.
> 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 nodejs@googlegroups.com
To unsubscribe from this group, send email to
nodejs+unsubscr...@googlegroups.com
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 nodejs+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to