Mark S. Miller (2014-09-11T14:00:34.000Z)
On Thu, Sep 11, 2014 at 6:20 AM, Florian Bösch <pyalot at gmail.com> wrote:

> await has also another problem in that if somewhere, deep down the call
> stack, something is intending to do async, then up the entire call stack
> everywhere you've got to insert await. It's a bit of a headache for code
> maintenance (hello bicycle repair man jam session), and it's also fairly
> unfriendly for library authors.
>
> There is a solution to that problem, which is not using generators if
> you'd want co-routines. If you want co-routine like behavior, please
> implement co-routines (and you can prop whatever scheduling/managing on top
> of that).
>
> An argument has been made in earlier discussions on that topic, that JS
> VMs can't deal with co-routines (garbage collection, DOM, whatever). But
> surely, if the VM can support generators/continuations, it could support
> full co-routines.
>

VM issues are not the argument against coroutines or deep generators. The
issue is that unpredictable interleaving makes reasoning about invariants
much too difficult. Without these, we have an important guarantee: When f
synchronously calls g, the only side effects that might have occurred by
the time g returns to f are those g might have caused. Thus, these are the
only side effect possibilities that f must worry about.

See section 18.3 of <http://www.erights.org/talks/thesis/markm-thesis.pdf>
and replace postfix diagonal uparrow with prefix "await". In ES7 the
example would be

    async function foo() { return bar(await getint(), y()); }
    ... await foo() ...

The net effect is like co-routines, except that the placement of "async"
and "await" -- like the diagonal uparrow in the text -- marks the places
where interleaving might occur. This is as close to coroutine support as we
should ever come.



> I'd recommend python's greenlet as an outstanding implementation of a
> co-routine interface that includes basically everything one could wish from
> it. I'd not consider python 3's "asyncio" a proper co-routine
> implementation (i.e. it's the same generator/await hack as is being
> discussed here).
>
> On Thu, Sep 11, 2014 at 3:05 PM, Kevin Smith <zenparsing at gmail.com> wrote:
>
>> Also, see https://github.com/lukehoban/ecmascript-asyncawait/issues/14
>> for previous discussion.
>>
>> On Thu, Sep 11, 2014 at 8:42 AM, Domenic Denicola <
>> domenic at domenicdenicola.com> wrote:
>>
>>> There are several problems solved by async/await instead of twisting
>>> generators:
>>>
>>> 1. What if you wanted to use generators for lazy sequences (iterables),
>>> instead of asynchronicity? If your framework assumes all generators are for
>>> async, you lose the original use case of generators.
>>>
>>> 2. Say what you mean. `function*` and `yield` mean something very
>>> different from `async function` and `await`, similar to how
>>> `Subclass.prototype = Object.create(Superclass.prototype);
>>> Subclass.prototype.constructor = Subclass` is different from `class
>>> Subclass extends Superclass`.
>>>
>>> 3. Operator precedence. You can do `await a + await b` to mean `(await
>>> a) + (await b)`, but `yield a + yield b` means `yield (a + (yield b))`.
>>>
>>> 4. Ability to produce promise-returning functions without buying into a
>>> specific framework that interprets generators in a certain way. E.g., you
>>> could use `async function f() { return 5; }` to return a promise for 5,
>>> which people can consume with `f().then(v => ...)`. If you try to do
>>> `function* f() { return 5; }` you will get an iterable, which is not
>>> understood to be asynchronous. (Hopefully my use of `return 5` for brevity
>>> instead of more complex code does not confuse this point for you.)
>>>
>>> As for stack traces, long stack trace support is a debugging feature,
>>> and the fact that `yield*` gets them right now doesn't mean that `await`
>>> won't get them in the future.
>>>
>>> -----Original Message-----
>>> From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of
>>> Jeswin Kumar
>>> Sent: Thursday, September 11, 2014 11:46
>>> To: es-discuss at mozilla.org
>>> Subject: Does async/await solve a real problem?
>>>
>>> Looking at my project (in which asynchronous calls are entirely done via
>>> generators), I can't see how async/await would simplify code for end-users
>>> like me (application programmers).
>>>
>>> End users write the spawn()/Q.async()/co() wrapper *at most* one single
>>> time in an application:
>>> 1. When using a framework like say koajs, you don't have to write it
>>> even once.
>>> 2. While not using a framework, you'd have to use the wrapper one single
>>> time in say, the main.js file.
>>>
>>> To use the example at
>>> http://wiki.ecmascript.org/doku.php?id=strawman:async_functions
>>>
>>> async function chainAnimationsAsync(elem, animations) { CODE; } is just
>>> function chainAnimationsAsync*(elem, animations) { same CODE; } when flow
>>> control is done by a framework or at the entry point to your application.
>>> spawn() isn't needed.
>>>
>>> I can't see how this will reduce application's code even a little. So my
>>> question is, is async/await needed?
>>>
>>>
>>> One more question
>>> --------------------------
>>> 1. yield is practically very difficult to use in a project because you
>>> don't get proper stack traces (at least with the current flow control
>>> libraries). You'd only see the last call which threw the error, and then
>>> functions from the flow control library immediately below that. I suppose
>>> the generators leading up to the erring generator are all suspended and
>>> wouldn't be on the stack frame chain.
>>>
>>> 2. yield* generator delegation solves this problem, you get real stack
>>> traces. I was able to get full stack traces simply by replacing all yield
>>> X() with yield* X()
>>>
>>> example code as in: https://github.com/chopachom/syncio
>>>
>>> So if there are valid use-cases for adding async/await to JS, shouldn't
>>> it be based on how yield* works rather than yield?
>>>
>>> -- Jes
>>>
>>> The Fora Project is coming...
>>> https://github.com/jeswin/fora
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>
>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>


-- 
    Cheers,
    --MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140911/39d8470c/attachment-0001.html>
domenic at domenicdenicola.com (2014-09-17T22:17:58.417Z)
VM issues are not the argument against coroutines or deep generators. The
issue is that unpredictable interleaving makes reasoning about invariants
much too difficult. Without these, we have an important guarantee: When f
synchronously calls g, the only side effects that might have occurred by
the time g returns to f are those g might have caused. Thus, these are the
only side effect possibilities that f must worry about.

See section 18.3 of http://www.erights.org/talks/thesis/markm-thesis.pdf and replace postfix diagonal uparrow with prefix "await". In ES7 the example would be

    async function foo() { return bar(await getint(), y()); }
    ... await foo() ...

The net effect is like co-routines, except that the placement of "async"
and "await" -- like the diagonal uparrow in the text -- marks the places
where interleaving might occur. This is as close to coroutine support as we
should ever come.