d at domenic.me (2015-07-07T02:07:43.846Z)
On Wed, Jun 24, 2015 at 3:17 PM, Mark S. Miller <erights at google.com> wrote:
> ```js
> flatMap([g1, g2]) is equivalent to
>
> (function*() {
> yield* wrap(g1, function.sent); // result of g1 ignored!
> return yield* wrap(g2, function.sent);
> ```
I think this second yield* should just be
return yield* g2;
On Wed, Jun 24, 2015 at 3:17 PM, Mark S. Miller <erights at google.com> wrote: > > >>> Jason Orendorff wrote: >>> >>>> Quick question about function.sent: >>>> >>>> As of ES6, there's this parallel between functions and generators: >>>> >>>> // how to wrap a function >>>> // f2 is equivalent to f, if f doesn't use `this`. >>>> function f(...) { ... } >>>> function f2(...args) { return f(...args); } >>>> >>>> // how to wrap a generator >>>> // g2 is equivalent to g, if g doesn't use `this`. >>>> function* g(...) { ... } >>>> function* g2(...args) { return yield* g(...args); } >>>> >>>> That is, λx.f(x) = f, a sort of beta-equivalence rule, and for >>>> generators, you just need to add `yield*` to get an analogous rule. My >>>> understanding is that this is one reason we have `yield*`. (Writing a >>>> wrapping function/generator that also covers `this` is left as an easy >>>> exercise.) >>>> >>>> Given function.sent, is there still a way to "wrap" a generator? >>>> >>> > > >> On Wed, Jun 24, 2015 at 2:17 PM, Brendan Eich <brendan at mozilla.org> >> wrote: >> >>> Hrm, the meeting notes don't quite capture it ( >>> https://github.com/tc39/tc39-notes/blob/bf5190257d22d1c700e203b28edc8d85ee3aadcc/es6/2015-05/may-27.md >>> is one view; my fault for not editing after), but we have discussed passing >>> function.sent into the sub-generator in the past. Ben Newman first raised >>> the idea the other year, but we finally all came to see at the last (May) >>> meeting that there's no good way to do it in general. >>> >>> When you write a delegating generator that does nothing else, it's >>> tempting to want function.sent delegation. But in general the yield* could >>> want a different first-next param than what was passed down, especially >>> when the delegator looks like this: >>> >>> function *g2(...args) { prolog code here; maybe-return yield* >>> g(...args); optional epilog here } >>> >>> See the discussion from the May meeting, I'll cite it here:""" >>> >>> MM: But it's passing something from before when yield * is evaluated. >>> >>> DH: I'm beginning to think that this is the wrong path (passing in >>> function.next via yield *). >>> >>> AWB: You could create some kind of wrapper if you wanted to pass in the >>> first value to the subgenerator. >>> >>> MM: Libraries could do this. >>> >>> yield * wrap(g,function.next); >>> >>> MM: "wrap" returns an iterator which wraps the generator which primes >>> the subgenerator with the supplied value. >>> """ >>> >>> Does this make sense? Sorry again for sparse notes. >>> >>> /be >>> >>> > Something strange and bizarre that Jafar and I just discovered after the > TC39 meeting: > > We all know that there are a set of conventional combinators, like > flatMap, that work fine for iterators. > > Iterators are uni-directional. Generators are bi-directional. (As Jara > observes: Generator implements Iterator, Observer) > > We thought that these combinators did not apply to generators in their > full bidirectional glory. We were wrong. > > Flatmap of generators can approximately be modeled in terms of "yield* > wrap" as follows: > > flatMap([g1, g2]) is equivalent to > > (function*() { > yield* wrap(g1, function.sent); // result of g1 ignored! > return yield* wrap(g2, function.sent); > I think this second yield* should just be return yield* g2; > }()) > > > > On Wed, Jun 24, 2015 at 3:04 PM, Jason Orendorff < > jason.orendorff at gmail.com> wrote: > >> On Wed, Jun 24, 2015 at 2:17 PM, Brendan Eich <brendan at mozilla.org> >> wrote: >> > MM: Libraries could do this. >> > >> > yield * wrap(g,function.next); >> > >> > MM: "wrap" returns an iterator which wraps the generator which primes >> the >> > subgenerator with the supplied value. >> >> Thanks for finding this discussion. This is exactly what I'm >> interested in. What does "wrap" look like? It seems like it would be >> pretty involved. >> > > Just showing the next method: > > function wrap(g, prime) { > let first = true; > return { > next(val) { > if (first) { > first = false; > return g.next(prime); > } else { > return g.next(val); > } > } > //... > }; > } > > > ALL CODE I WROTE ABOVE IS UNTESTED. > > Does this make sense? If anyone tests it, does it work? > > > -- > Cheers, > --MarkM > -- Cheers, --MarkM -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150624/dc2ecdd7/attachment.html>