I have no idea why both you and Brendan assert that I was arguing/
rehashing for deep delimited continuations (let alone call/cc).

Because you wrote:

"1 can be worked around, but not with the usual tools of function definitions and calls - "yield" forces use of "function*" and "yield*" for abstracting over expressions containing it."

and later:

"For instance, we cannot write

   function* g() {  (function(){ yield 1 })() }

This certainly looks like you want a deep continuation.

Ah, thanks, that explains it. Yes, I was listing examples that trouble
me about the current design, I was suggesting changes to that
design, and some of the examples could only be solved by deeper
continuations.
The point of departure is that my suggested changes wouldn't actually
solve all the cases that trouble me (in particular, not those cases that
would depend on deep continuations). Issues that I've tried to address
include:

1. the example above doesn't require "deep" continuation any more
than local variable declarations in a generator require them. Let me change the example to use immediately applied arrow functions (to avoid any special once-per-function-body handling of "this" and "arguments"); then I would expect

       function* g() {  (()=>{ let x = 1; yield x })() }

   to be equivalent to

       function* g() {  { let x = 1; yield x } }

and if the latter is considered valid/shallow, I would expect the former to be valid/shallow, too.

2. I'd like to decouple generators from "function", to avoid interference
between the two features. For concreteness, let me assume a block form of generators as "do* { ... }" (delimiting continuations to the block, giving a generator- valued expression). Then the example would read (ignoring item 1 above for now, so we have to use "yield*"):

       var g = () => do* { yield* (()=> do* { yield 1 } )() }

With "function", this would be slightly longer than with the current spec, but since generators are now decoupled from "function", we can use (arrow) functions (our means of functional abstraction) freely -
   generators are simply another class of object to write functions over.

   We could even re-introduce

       function* f() { ... }

   as mere syntactic sugar for

       function f() { return do* { ... } }

3. I'd like to see a standard iterator library, with things like zip and
   feed (the exact contents of such a library would evolve in practice,
   not from a spec, but the spec could provide a seed, and organize
the evolution), and I would like to see more support for composing generators.

   Using the current spec, we could define

       function* then(g1,g2) { yield* g1; yield* g2 }

   and use this to combine generators via ES5 array iterations

       [1,2,3].map(function*(x) { yield x }).reduce(then)

   or, assuming item 2 above,

       function then(g1,g2) { return do* { yield* g1; yield* g2 } }

       [1,2,3].map(x=>do* { yield x }).reduce(then)

This, as well as my generators-as-monads gist, suggest that we could let generators return their completion value and have them
   implement monadic .then, for easy composition using the monadic
   set of tools.

   And since "yield*" is essentially a mini-interpreter built on top of
   "yield", the composition library could include alternative interpreters
   (eg, support for early return).

So, none of my suggestions require deep continuations. Nevertheless,
I'm having trouble distinguishing local blocks in shallow-continuation
generators from deep-continuation generators. So I'd be interested to hear the precise arguments against deep delimited continuations (link to meeting notes/mailing list thread would be fine).

Claus


_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to