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