David Herman (2013-05-02T18:07:03.000Z)
Brendan reminded me I never replied to the earlier part of this thread.

On Apr 29, 2013, at 8:37 AM, Andy Wingo <wingo at igalia.com> wrote:

> For what it's worth (which is very little) this seems like a decent
> plan to me.

Actually it's worth a lot to me! Your blog post on StopIteration was part of what got me thinking again about it and prodded me to bring it up with TC39.

> The desugaring of "yield* EXPR" with boxed return values would be:
> 
>  let (g = EXPR) {
>    let received = void 0, send = true;
>    while (true) {
>      let next = send ? g.send(received) : g.throw(received);
>      if (next.done)
>        break;
>      try {
>        received = yield next.value;  // ***
>        send = true;
>      } catch (e) {
>        received = e;
>        send = false;
>      }
>    }    
>    next.value;
>  }
> 
> As you can see on the line marked "***", to desugar to plain "yield" you
> would have to unbox the value and then allow yield to rebox it.  This
> loses any state on "next" -- there could be other properties set on
> "next", for example if "g" is a non-generator.
> 
> IMHO yield* should be specified to return the result object as-is,
> without re-boxing.  This precludes a straightforward desugaring, but it
> is probably more flexible.

This is an interesting question. I agree that the intuition of yield* is chaining together continuation frames and therefore "just pass on through" seems like the Right Thing. It's only maybe slightly disconcerting that yield* therefore actually gives you additional power that you can't otherwise express locally (i.e., you have to transform the entire containing generator function). But I'm with you, this seems right to me.

Dave
github at esdiscuss.org (2013-07-12T02:27:20.686Z)
Brendan reminded me I never replied to the earlier part of this thread.

On Apr 29, 2013, at 8:37 AM, Andy Wingo <wingo at igalia.com> wrote:

> For what it's worth (which is very little) this seems like a decent
> plan to me.

Actually it's worth a lot to me! Your blog post on `StopIteration` was part of what got me thinking again about it and prodded me to bring it up with TC39.

> The desugaring of `yield* EXPR` with boxed return values would be:
> 
> ```js
> let (g = EXPR) {
>   let received = void 0, send = true;
>   while (true) {
>     let next = send ? g.send(received) : g.throw(received);
>     if (next.done)
>       break;
>     try {
>       received = yield next.value;  // ***
>       send = true;
>     } catch (e) {
>       received = e;
>       send = false;
>     }
>   }    
>   next.value;
> }
> ```
> 
> As you can see on the line marked "***", to desugar to plain `yield` you
> would have to unbox the value and then allow yield to rebox it.  This
> loses any state on `next` -- there could be other properties set on
> `next`, for example if `g` is a non-generator.
> 
> IMHO `yield*` should be specified to return the result object as-is,
> without re-boxing.  This precludes a straightforward desugaring, but it
> is probably more flexible.

This is an interesting question. I agree that the intuition of `yield*` is chaining together continuation frames and therefore "just pass on through" seems like the Right Thing. It's only maybe slightly disconcerting that `yield*` therefore actually gives you additional power that you can't otherwise express locally (i.e., you have to transform the entire containing generator function). But I'm with you, this seems right to me.