Jason Orendorff (2015-06-25T15:17:30.000Z)
On Wed, Jun 24, 2015 at 3:17 PM, Mark S. Miller <erights at google.com> wrote:
> Just showing the next method:
>
> function wrap(g, prime) {
>   let first = true;
>   return {
>     next(val) {
>       if (first) {
>         first = false;
>         return g.next(prime);

Oh, I see. We can use an intermediate wrapper object here that's not a
generator.

OK, I don't imagine people doing this in the case where they're using
generators to implement asynchronous processes. I suppose they just
won't use function.next in that case. Which is fine.

Still, it's funny that at the language level we can't have an
"elimination form" in `yield* f(...)` that's directly dual with the
"introduction form" of `function*(...){...}`. Is there some PLT-ish
explanation for the asymmetry? Just hoping to understand a little
better the relationship between functions and generators.

I'm not sure it'll be clear what I mean by "relationship". I mean a
mathematical sort of relationship. If you think of the statements and
operators of JavaScript as combinators in some kind of algebra on
computations, both functions and generators are built up *mostly* from
the same combinators, and they have analogous behavior. That is, they
follow the same rules of execution: those rules are only specified
once, not twice. The differences are around invocation, but even
there, though you have to use slightly different syntax, some
analogies hold (as in my original post on this thread).

My sense is that function.next is outside this relationship, and it
shows as a bit of a wart every time you write abstract code about
generators. For example, Mark's flatMap on generators must pass
undefined as the first value to g2.

-j
d at domenic.me (2015-07-07T02:08:35.206Z)
On Wed, Jun 24, 2015 at 3:17 PM, Mark S. Miller <erights at google.com> wrote:
> Just showing the next method:

Oh, I see. We can use an intermediate wrapper object here that's not a
generator.

OK, I don't imagine people doing this in the case where they're using
generators to implement asynchronous processes. I suppose they just
won't use function.next in that case. Which is fine.

Still, it's funny that at the language level we can't have an
"elimination form" in `yield* f(...)` that's directly dual with the
"introduction form" of `function*(...){...}`. Is there some PLT-ish
explanation for the asymmetry? Just hoping to understand a little
better the relationship between functions and generators.

I'm not sure it'll be clear what I mean by "relationship". I mean a
mathematical sort of relationship. If you think of the statements and
operators of JavaScript as combinators in some kind of algebra on
computations, both functions and generators are built up *mostly* from
the same combinators, and they have analogous behavior. That is, they
follow the same rules of execution: those rules are only specified
once, not twice. The differences are around invocation, but even
there, though you have to use slightly different syntax, some
analogies hold (as in my original post on this thread).

My sense is that function.next is outside this relationship, and it
shows as a bit of a wart every time you write abstract code about
generators. For example, Mark's flatMap on generators must pass
undefined as the first value to g2.