On 9/11/14, 10:22 AM, Florian Bösch wrote:
A -> B -> C -> D -> E changes to

A -> B -> C -> D -> async E and causes

A await -> B await -> C await -> D await -> async E

And of course if A, B, C or D is used anywhere else it percolates trough the entire call graph.
Sort of true, but this is no worse than the status quo.

function A() { return B(); }
function B() { return C(); }
function D() { return D(); }
function E() { return 42; } -> function E() { return new Promise(function(res, rej) { res(42); }); }

I said "sort of" above because it's also worth pointing out that, in some cases, outer plain functions can still consume async functions without needing to themselves become async. The case arises where the result of the outer plain function doesn't depend on the async result of the inner function. Many cases don't apply here, but it's worth pointing out to show that consumption of async functions isn't *always* stack-viral:

function add(a, b) {
  var logSuccess = log('adding ' + a + ' and ' + b);
  if (!logSucces) {
    console.warn('log failed!');
  }
  return a + b;
}

function log(msg) {
  return logger.syncAppend(msg);
}

changes to

function add(a, b) {
  log('adding ' + a + ' and ' + b).catch(function(res) {
    console.warn('log failed!');
  }).done();

  return a + b;
}

async function log(msg) {
  return logger.asyncAppend(msg);
}

-Jeff

Trying to protect people from interlaved code execution effects is noble. But doing so by introducing a rote thing to type everytime you change the code somewhere underneath is wrong. It's wrong because it breaks logic isolation, it becomes impossible to change part of the library/utiity code without this change affecting all code that uses it. This guarantees that it doesn't happen in practice, because it's too painful to do. It requires the code, that uses other code, to know about the internal behavior of that code.

If say, I'd propose a semantic that required you to write "foo" in the code, but just for those pieces of code that contain mentions of "bar", or that reference code that contains "bar" to the Nth degree, you'd accuse me of trying to introduce a purposefully unusable feature. How is await/async not an unusable feature?



On Thu, Sep 11, 2014 at 4:00 PM, Mark S. Miller <[email protected] <mailto:[email protected]>> wrote:

    On Thu, Sep 11, 2014 at 6:20 AM, Florian Bösch <[email protected]
    <mailto:[email protected]>> 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
        <[email protected] <mailto:[email protected]>> 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
            <[email protected]
            <mailto:[email protected]>> 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:[email protected]
                <mailto:[email protected]>] On Behalf Of
                Jeswin Kumar
                Sent: Thursday, September 11, 2014 11:46
                To: [email protected] <mailto:[email protected]>
                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
                [email protected] <mailto:[email protected]>
                https://mail.mozilla.org/listinfo/es-discuss
                _______________________________________________
                es-discuss mailing list
                [email protected] <mailto:[email protected]>
                https://mail.mozilla.org/listinfo/es-discuss



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



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




-- Cheers,
        --MarkM




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

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

Reply via email to