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.


Reply via email to