Re: Conditional await, anyone?

2019-11-16 Thread #!/JoePea
I haven't read the whole thread, but I also disliked the ugly
conditional checking I had to do to get faster results.

I agree that this would changed perceived code execution order
(unexpectedly, a breaking change).

I believe that a better solution would be to make it explicit in the
function definition, so that it carries up into caller code:

```js
async? function foo() { ... }
```

Now, the user of the function must be required to use `await?` and
thus has to be forced to think that the `foo` function might possibly
run async, or might not. Using `await` on an `async? function` would
be a runtime error, to further prevent possible confusion and errors.

Only with a construct like `async? function` could I see this becoming
possible, so that there aren't any surprising breaking changes in
downstream projects.

On Tue, Oct 15, 2019 at 12:26 AM Andrea Giammarchi

 wrote:
>
> > You still seem to be misunderstanding what the execution order difference 
> > is about.
>
> If to stop this thread you need me to say I am confused about anything then 
> fine, "I am confused", but if you keep changing my examples to make your 
> point then this conversation goes nowhere, so I am officially out of this 
> thread.
>
> Best Regards.
>
> On Mon, Oct 14, 2019 at 10:41 PM Tab Atkins Jr.  wrote:
>>
>> On Sat, Oct 12, 2019 at 7:19 AM Andrea Giammarchi
>>  wrote:
>> > in order to work, `await` must be executed in an async scope/context 
>> > (either top level or within a closure).
>> >
>> > In such case, either somebody is awaiting the result of that `async` 
>> > execution, or the order doesn't matter.
>>
>> That's definitely not true. I gave you an explicit example where the
>> order differs. That example code is realistic if you're using the
>> async call for side-effects only (and thus don't care about the
>> returned promise), or if you're storing the returned promise in a
>> variable so you can pass it to one of the promise combinators later.
>> In either of these cases the order of execution between the sync and
>> async code can definitely matter.
>>
>> > The following two examples produce indeed the very same result:
>> >
>> > ```js
>> > (async () => { return 1; })().then(console.log);
>> > console.log(2);
>> >
>> > (async () => { return await 1; })().then(console.log);
>> > console.log(2);
>> > ```
>>
>> In both of these cases, you're doing no additional work after the
>> "maybe async" point. That is the exact part that moves in execution
>> order between the two cases, so obviously you won't see any
>> difference.  Here's a slightly altered version that shows off the
>> difference:
>>
>> ```js
>> (async () => { 1; console.log("async"); return 3; })().then(console.log);
>> console.log(2);
>>
>> (async () => { await 1; console.log("async"); return 3; 
>> })().then(console.log);
>> console.log(2);
>> ```
>>
>> In the first you'll log "async", "2", "3". In the second you'll log
>> "2", "async", "3".
>>
>> > As summary: the proposal was to help engines be faster when it's possible, 
>> > but devs are confused by the syntax, and maybeat the end there wouldn't be 
>> > as many benefits compared to the apparent confusion this proposal would 
>> > add.
>>
>> You still seem to be misunderstanding what the execution order
>> difference is about. Nobody's confused about the syntax; it's clear
>> enough. It just does bad, confusing things as you've presented it.
>>
>> As I said in earlier message, there *is* a way to eliminate the
>> execution-order difference (making it so the only difference would be
>> the number of microtasks when your function awaits *multiple* sync
>> values), which I thought you'd come up with at some point, but I'm
>> pretty sure it was just me misunderstanding what you'd said.
>>
>> ~TJ
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-15 Thread Andrea Giammarchi
> You still seem to be misunderstanding what the execution order difference
is about.

If to stop this thread you need me to say I am confused about anything then
fine, "I am confused", but if you keep changing my examples to make your
point then this conversation goes nowhere, so I am officially out of this
thread.

Best Regards.

On Mon, Oct 14, 2019 at 10:41 PM Tab Atkins Jr. 
wrote:

> On Sat, Oct 12, 2019 at 7:19 AM Andrea Giammarchi
>  wrote:
> > in order to work, `await` must be executed in an async scope/context
> (either top level or within a closure).
> >
> > In such case, either somebody is awaiting the result of that `async`
> execution, or the order doesn't matter.
>
> That's definitely not true. I gave you an explicit example where the
> order differs. That example code is realistic if you're using the
> async call for side-effects only (and thus don't care about the
> returned promise), or if you're storing the returned promise in a
> variable so you can pass it to one of the promise combinators later.
> In either of these cases the order of execution between the sync and
> async code can definitely matter.
>
> > The following two examples produce indeed the very same result:
> >
> > ```js
> > (async () => { return 1; })().then(console.log);
> > console.log(2);
> >
> > (async () => { return await 1; })().then(console.log);
> > console.log(2);
> > ```
>
> In both of these cases, you're doing no additional work after the
> "maybe async" point. That is the exact part that moves in execution
> order between the two cases, so obviously you won't see any
> difference.  Here's a slightly altered version that shows off the
> difference:
>
> ```js
> (async () => { 1; console.log("async"); return 3; })().then(console.log);
> console.log(2);
>
> (async () => { await 1; console.log("async"); return 3;
> })().then(console.log);
> console.log(2);
> ```
>
> In the first you'll log "async", "2", "3". In the second you'll log
> "2", "async", "3".
>
> > As summary: the proposal was to help engines be faster when it's
> possible, but devs are confused by the syntax, and maybeat the end there
> wouldn't be as many benefits compared to the apparent confusion this
> proposal would add.
>
> You still seem to be misunderstanding what the execution order
> difference is about. Nobody's confused about the syntax; it's clear
> enough. It just does bad, confusing things as you've presented it.
>
> As I said in earlier message, there *is* a way to eliminate the
> execution-order difference (making it so the only difference would be
> the number of microtasks when your function awaits *multiple* sync
> values), which I thought you'd come up with at some point, but I'm
> pretty sure it was just me misunderstanding what you'd said.
>
> ~TJ
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-14 Thread Tab Atkins Jr.
On Sat, Oct 12, 2019 at 7:19 AM Andrea Giammarchi
 wrote:
> in order to work, `await` must be executed in an async scope/context (either 
> top level or within a closure).
>
> In such case, either somebody is awaiting the result of that `async` 
> execution, or the order doesn't matter.

That's definitely not true. I gave you an explicit example where the
order differs. That example code is realistic if you're using the
async call for side-effects only (and thus don't care about the
returned promise), or if you're storing the returned promise in a
variable so you can pass it to one of the promise combinators later.
In either of these cases the order of execution between the sync and
async code can definitely matter.

> The following two examples produce indeed the very same result:
>
> ```js
> (async () => { return 1; })().then(console.log);
> console.log(2);
>
> (async () => { return await 1; })().then(console.log);
> console.log(2);
> ```

In both of these cases, you're doing no additional work after the
"maybe async" point. That is the exact part that moves in execution
order between the two cases, so obviously you won't see any
difference.  Here's a slightly altered version that shows off the
difference:

```js
(async () => { 1; console.log("async"); return 3; })().then(console.log);
console.log(2);

(async () => { await 1; console.log("async"); return 3; })().then(console.log);
console.log(2);
```

In the first you'll log "async", "2", "3". In the second you'll log
"2", "async", "3".

> As summary: the proposal was to help engines be faster when it's possible, 
> but devs are confused by the syntax, and maybeat the end there wouldn't be as 
> many benefits compared to the apparent confusion this proposal would add.

You still seem to be misunderstanding what the execution order
difference is about. Nobody's confused about the syntax; it's clear
enough. It just does bad, confusing things as you've presented it.

As I said in earlier message, there *is* a way to eliminate the
execution-order difference (making it so the only difference would be
the number of microtasks when your function awaits *multiple* sync
values), which I thought you'd come up with at some point, but I'm
pretty sure it was just me misunderstanding what you'd said.

~TJ
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-12 Thread Andrea Giammarchi
in order to work, `await` must be executed in an async scope/context
(either top level or within a closure).

In such case, either somebody is awaiting the result of that `async`
execution, or the order doesn't matter.

The following two examples produce indeed the very same result:

```js
(async () => { return 1; })().then(console.log);
console.log(2);

(async () => { return await 1; })().then(console.log);
console.log(2);
```

Except the second one will be scheduled a micro task too far.

Since nobody counts the amount of microtasks per async function execution,
the result is practically the same, except the second example is always
slower.

Putting all together:

```js
(async () => { return await 'third'; })().then(console.log);
(async () => { return 'second'; })().then(console.log);
console.log('first');
```

If you `await` the return of an async function, you are consuming that
microtask regardless, which is what `await?` here would like to avoid: do
not create a micro task when it's not necessary.

There's no footgun as the `await?` is an explicit intent from the
developer, so if the developer knows what s/he's doing, can use `await?`,
otherwise if the order of the microtask matters at all, can always just use
`await`.

As summary: the proposal was to help engines be faster when it's possible,
but devs are confused by the syntax, and maybeat the end there wouldn't be
as many benefits compared to the apparent confusion this proposal would add.

I hope I've explained properly what was this about.

Regards


On Fri, Oct 11, 2019 at 10:43 PM Tab Atkins Jr. 
wrote:

> On Fri, Oct 11, 2019 at 1:15 AM Andrea Giammarchi
>  wrote:
> > Again, the `await?` is sugar for the following:
> >
> > ```js
> > const value = await? callback();
> >
> > // as sugar for
> > let value = callback();
> > if ('then' in value)
> >   value = await value;
> > ```
>
> Okay, so that has the "you can't predict execution order any more"
> problem. But that's not consistent with what you said in "otherwise
> schedule a single microtask if none has been scheduled already, or
> queue this result to the previous scheduled one", which implies a
> different desugaring:
>
> ```js
> let value = callback();
> if('then' in value || thisFunctionHasntAwaitedYet)
>   value = await value;
> ```
>
> *This* desugaring has a consistent execution order, and still meets
> your goal of "don't add a bunch of microtask checkpoints for
> synchronous values".
>
> Put another way, this `await?` is equivalent to `await` *if* you're
> still in the "synchronously execute until you hit the first await"
> phase of executing an async function; but it's equivalent to your
> simpler desugaring ("await only if this is a thenable") after that.
>
> > but since I've stated already I have no interest anymore in this
> proposal, we can also stop explaining to each others things we know already.
>
> I'm fine if you want to drop it, but we're not explaining things we
> already know to each other. At least one of us is confused about
> what's being proposed. And the altered desugaring I give up above at
> least has a chance of happening; the only issue might be the
> observability of how many microtasks get scheduled. If that's not a
> problem, it might be possible to suggest this as an actual change to
> how `await` works.
>
> ~TJ
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-11 Thread Tab Atkins Jr.
On Fri, Oct 11, 2019 at 1:15 AM Andrea Giammarchi
 wrote:
> Again, the `await?` is sugar for the following:
>
> ```js
> const value = await? callback();
>
> // as sugar for
> let value = callback();
> if ('then' in value)
>   value = await value;
> ```

Okay, so that has the "you can't predict execution order any more"
problem. But that's not consistent with what you said in "otherwise
schedule a single microtask if none has been scheduled already, or
queue this result to the previous scheduled one", which implies a
different desugaring:

```js
let value = callback();
if('then' in value || thisFunctionHasntAwaitedYet)
  value = await value;
```

*This* desugaring has a consistent execution order, and still meets
your goal of "don't add a bunch of microtask checkpoints for
synchronous values".

Put another way, this `await?` is equivalent to `await` *if* you're
still in the "synchronously execute until you hit the first await"
phase of executing an async function; but it's equivalent to your
simpler desugaring ("await only if this is a thenable") after that.

> but since I've stated already I have no interest anymore in this proposal, we 
> can also stop explaining to each others things we know already.

I'm fine if you want to drop it, but we're not explaining things we
already know to each other. At least one of us is confused about
what's being proposed. And the altered desugaring I give up above at
least has a chance of happening; the only issue might be the
observability of how many microtasks get scheduled. If that's not a
problem, it might be possible to suggest this as an actual change to
how `await` works.

~TJ
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-11 Thread Andrea Giammarchi
Again, the `await?` is sugar for the following:

```js
const value = await? callback();

// as sugar for
let value = callback();
if ('then' in value)
  value = await value;
```

but since I've stated already I have no interest anymore in this proposal,
we can also stop explaining to each others things we know already.

Best Regards

On Fri, Oct 11, 2019 at 1:32 AM Tab Atkins Jr.  wrote:

> On Wed, Oct 9, 2019 at 11:17 PM Andrea Giammarchi
>  wrote:
> > > What's the order of the logs?
> >
> > Exactly the same, as the `await?` is inevitably inside an `async`
> function which would grant a single microtask instead of N.
>
> I think you're misreading my example?  Check this out:
> http://software.hixie.ch/utilities/js/live-dom-viewer/saved/7271
>
> ```html
> 
> 
> function one() {
>   oneAsync();
>   w("one A");
> }
> async function oneAsync() {
>   await Promise.resolve();
>   w("one B");
> }
>
> function two() {
>   twoAsync();
>   w("two A");
> }
>
> async function twoAsync() {
>   // await? true;
>   w("two B");
> }
>
> one();
> two();
> 
> ```
>
> This script logs:
>
> ```
> log: one A
> log: two B
> log: two A
> log: one B
> ```
>
> A and B are logged in different order depends on whether there's an
> `await` creating a microtask checkpoint or not. `await? true` won't
> create a microtask checkpoint, so you'll get the two() behavior,
> printing B then A. `await? Promise.resolve(true)` will create one, so
> you'll get the one() behavior, printing A then B.
>
> > If `maybeAsync` returns twice non promises results, there is only one
> microtask within the async `tasks` function, that would linearly collect
> all non promises, so that above example could have 1, 2, max 4 microtasks,
> instead of always 4
> > .
> > To explain `await?` in steps:
> >
> >   * is the awaited value a promise? schedule microtask
> >   * otherwise schedule a single microtask if none has been scheduled
> already, or queue this result to the previous scheduled one
> >
> > This would grant same linear order and save time.
>
> Ah, your earlier posts didn't say that `await? nonPromise` *would*
> schedule a microtask in some cases! That does change things.  Hm, I
> wonder if this is observably different from the current behavior?
>
> ~TJ
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-10 Thread Tab Atkins Jr.
On Wed, Oct 9, 2019 at 11:17 PM Andrea Giammarchi
 wrote:
> > What's the order of the logs?
>
> Exactly the same, as the `await?` is inevitably inside an `async` function 
> which would grant a single microtask instead of N.

I think you're misreading my example?  Check this out:
http://software.hixie.ch/utilities/js/live-dom-viewer/saved/7271

```html


function one() {
  oneAsync();
  w("one A");
}
async function oneAsync() {
  await Promise.resolve();
  w("one B");
}

function two() {
  twoAsync();
  w("two A");
}

async function twoAsync() {
  // await? true;
  w("two B");
}

one();
two();

```

This script logs:

```
log: one A
log: two B
log: two A
log: one B
```

A and B are logged in different order depends on whether there's an
`await` creating a microtask checkpoint or not. `await? true` won't
create a microtask checkpoint, so you'll get the two() behavior,
printing B then A. `await? Promise.resolve(true)` will create one, so
you'll get the one() behavior, printing A then B.

> If `maybeAsync` returns twice non promises results, there is only one 
> microtask within the async `tasks` function, that would linearly collect all 
> non promises, so that above example could have 1, 2, max 4 microtasks, 
> instead of always 4
> .
> To explain `await?` in steps:
>
>   * is the awaited value a promise? schedule microtask
>   * otherwise schedule a single microtask if none has been scheduled already, 
> or queue this result to the previous scheduled one
>
> This would grant same linear order and save time.

Ah, your earlier posts didn't say that `await? nonPromise` *would*
schedule a microtask in some cases! That does change things.  Hm, I
wonder if this is observably different from the current behavior?

~TJ
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-10 Thread Andrea Giammarchi
> What's the order of the logs?

Exactly the same, as the `await?` is inevitably inside an `async` function
which would grant a single microtask instead of N.

Example:

```js
async function tasks() {
  await? maybeAsync();
  await? maybeAsync();
  await? maybeAsync();
}

tasks();
```

If `maybeAsync` returns twice non promises results, there is only one
microtask within the async `tasks` function, that would linearly collect
all non promises, so that above example could have 1, 2, max 4 microtasks,
instead of always 4
.
To explain `await?` in steps:

  * is the awaited value a promise? schedule microtask
  * otherwise schedule a single microtask if none has been scheduled
already, or queue this result to the previous scheduled one

This would grant same linear order and save time.

However, like others said already in the twitter thread, we all wish
`await` was already working like that by default, while it seems to
unconditionally create micro tasks even when it's not strictly necessary.




On Wed, Oct 9, 2019 at 11:47 PM Tab Atkins Jr.  wrote:

> On Wed, Oct 9, 2019 at 12:08 AM Andrea Giammarchi
>  wrote:
> > I don't know why this went in a completely unrelated direction so ...
> I'll try to explain again what is `await?` about.
>
> Nah, we got it. Our complaint was still about the semantics.
>
> > ```js
> > const value = await? callback();
> >
> > // as sugar for
> > let value = callback();
> > if ('then' in value)
> >   value = await value;
> > ```
> >
> > The order is guaranteed and linear in every case, so that nothing
> actually change logically speaking, and the hint would be about
> performance, 'cause engines don't apparently optimize non-promise based
> cases.
>
> Expand that code so there's a caller:
>
> ```js
> function one() {
>   two();
>   console.log("one");
> }
> async function two() {
>   await? maybeAsync();
>   console.log("two");
> }
> ```
>
> What's the order of the logs?
>
> If maybeAsync() is synchronous, then one() calls two(), two() calls
> maybeAsync() which returns immediately, and it continues to log "two"
> before ending and returning execution to one(), which then logs "one"
> and ends.
>
> If maybeAsync() returns a promise, then one() calls two(), two calls
> maybeAsync() then freezes while it waits for the promise to resolve,
> returning execution to one(). Since one() isn't awaiting the promise
> returned by two(), it just immediately continues and logs "one" then
> ends. At some point later in execution, the maybeAsync() promise
> resolves, two() unfreezes, then it logs "two".
>
> So no, the order is not guaranteed. It's unpredictable and depends on
> whether the function being await?'d returns a promise or not. If you
> don't know what maybeAsync() returns, you won't be able to predict
> your own execution flow, which is dangerous and a very likely source
> of bugs.
>
> ~TJ
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-09 Thread Tab Atkins Jr.
On Wed, Oct 9, 2019 at 12:08 AM Andrea Giammarchi
 wrote:
> I don't know why this went in a completely unrelated direction so ... I'll 
> try to explain again what is `await?` about.

Nah, we got it. Our complaint was still about the semantics.

> ```js
> const value = await? callback();
>
> // as sugar for
> let value = callback();
> if ('then' in value)
>   value = await value;
> ```
>
> The order is guaranteed and linear in every case, so that nothing actually 
> change logically speaking, and the hint would be about performance, 'cause 
> engines don't apparently optimize non-promise based cases.

Expand that code so there's a caller:

```js
function one() {
  two();
  console.log("one");
}
async function two() {
  await? maybeAsync();
  console.log("two");
}
```

What's the order of the logs?

If maybeAsync() is synchronous, then one() calls two(), two() calls
maybeAsync() which returns immediately, and it continues to log "two"
before ending and returning execution to one(), which then logs "one"
and ends.

If maybeAsync() returns a promise, then one() calls two(), two calls
maybeAsync() then freezes while it waits for the promise to resolve,
returning execution to one(). Since one() isn't awaiting the promise
returned by two(), it just immediately continues and logs "one" then
ends. At some point later in execution, the maybeAsync() promise
resolves, two() unfreezes, then it logs "two".

So no, the order is not guaranteed. It's unpredictable and depends on
whether the function being await?'d returns a promise or not. If you
don't know what maybeAsync() returns, you won't be able to predict
your own execution flow, which is dangerous and a very likely source
of bugs.

~TJ
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-09 Thread Herby Vojčík

Hi!

First, experiences of this guy 
https://medium.com/@bluepnume/intentionally-unleashing-zalgo-with-promises-ab3f63ead2fd 
seem to refute the problematicity of zalgo.


Second, I actually have the use case of this pattern (though actually 
it's not a use case for a new syntax). In Amber Smalltalk 
(implementation running of top of JS engine), it would immensely help to 
be able to have classical "proxied message send" case, where message 
send is asynchronous in the background. As Amber compiles the code 
itself, you may say "compile it so you simply await every message send", 
but then, code that _must be_ synchronous (callbacks used in external JS 
libs API) will fail. Having two modes is not an option. So I would 
really use the option to have message sends synchronous by default, but 
in the case they _can be_ asynchronous, to be able to let them be that way.


Actually, the paypal guy mentioned in the first paragraph has similar 
case (inter-frame RPC). Using his ZalgoPromise I could compile the 
things like


  ZalgoPromise.resolve(make the message send).then(function (result) ...

Herby

On 8. 10. 2019 22:25, Tab Atkins Jr. wrote:

I'm not sure I understand the intended use-case here.  If the author
knows the function they're calling is async, they can use `await`
normally. If they know it's not async, they can avoid `await`
altogether. If they have no idea whether it's async or not, that means
they just don't understand what the function is returning, which
sounds like a really bad thing that they should fix?  And in that
case, as Gus says, `await?`'s semantics would do some confusing things
to execution order, making the line after the `await?` either run
*before* or *after* the calling code, depending on whether the await'd
value was a promise or not.

~TJ
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-09 Thread Isiah Meadows
I had a similar example in real-world code, but it was just to merge
sync and async into the same code path. I handled it by using
generators and basically running them myself:
https://github.com/isiahmeadows/mithril-node-render/blob/v2/index.js#L195-L206

In either case, I'm not sure it's worth adding new syntax for it.

-

Isiah Meadows
cont...@isiahmeadows.com
www.isiahmeadows.com

On Wed, Oct 9, 2019 at 3:08 AM Andrea Giammarchi
 wrote:
>
> I don't know why this went in a completely unrelated direction so ... I'll 
> try to explain again what is `await?` about.
>
> My first two examples show a relevant performance difference between the 
> async code and the sync one.
>
> The async code though, has zero reasons to be async and so much slower.
>
> ```js
> (async () => {
>   console.time('await');
>   const result = await (async () => [await 1, await 2, await 3])();
>   console.timeEnd('await');
>   return result;
> })();
> ```
>
> Why would `await 1` ever need to create a micro task, if already executed 
> into a scheduled one via async?
>
> Or in general, why any callback that would early return a value that is not a 
> promise should create a micro task?
>
> So the proposal was implemented in an attempt to de-sugar `await?` into the 
> steps proposed by the dev I've interacted with:
>
> ```js
> const value = await? callback();
>
> // as sugar for
> let value = callback();
> if ('then' in value)
>   value = await value;
> ```
>
> The order is guaranteed and linear in every case, so that nothing actually 
> change logically speaking, and the hint would be about performance, 'cause 
> engines don't apparently optimize non-promise based cases.
>
> However, since the initial intent/proposal about performance got translated 
> into everything else, I've instantly lost interest myself as it's evident an 
> `await?` would causes more confusion than it solves.
>
> I am also not answering other points as not relevant for this idea/proposal.
>
> Thanks regardless for sharing your thoughts, it helped me see it would 
> confuse developers.
>
> Best Regards
>
>
>
>
>
> On Tue, Oct 8, 2019 at 11:58 PM Dan Peddle  wrote:
>>
>> Have to agree, mixing sync and async code like this looks like a disaster 
>> waiting to happen. Knowing which order your code will be executed in might 
>> seem not so important for controlled environments where micro optimisations 
>> are attractive, but thinking about trying to track down a bug through this 
>> would drive me nuts.
>>
>> Imagine you have a cached value which can be retrieved synchronously - other 
>> code which runs in order, and perhaps not directly part of this chain, would 
>> be fine. When it’s not there, zalgo would indeed be released. The solution 
>> to this is to use promises (as I’m sure you know) so you have a consistent 
>> way of saying when something is ready... otherwise it’s thenable sniffing 
>> all the way through the codebase.
>>
>> Async infers some kind of IO or deferred process, scheduling. If there’s a 
>> dependency, then we need to express that. That it may be in some cases 
>> available synchronously seems like something to be extremely wary of.
>>
>> > On 8. Oct 2019, at 22:25, Tab Atkins Jr.  wrote:
>> >
>> > I'm not sure I understand the intended use-case here.  If the author
>> > knows the function they're calling is async, they can use `await`
>> > normally. If they know it's not async, they can avoid `await`
>> > altogether. If they have no idea whether it's async or not, that means
>> > they just don't understand what the function is returning, which
>> > sounds like a really bad thing that they should fix?  And in that
>> > case, as Gus says, `await?`'s semantics would do some confusing things
>> > to execution order, making the line after the `await?` either run
>> > *before* or *after* the calling code, depending on whether the await'd
>> > value was a promise or not.
>> >
>> > ~TJ
>> > ___
>> > es-discuss mailing list
>> > es-discuss@mozilla.org
>> > https://mail.mozilla.org/listinfo/es-discuss
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-09 Thread Andrea Giammarchi
I don't know why this went in a completely unrelated direction so ... I'll
try to explain again what is `await?` about.

My first two examples show a relevant performance difference between the
async code and the sync one.

The async code though, has zero reasons to be async and so much slower.

```js
(async () => {
  console.time('await');
  const result = await (async () => [await 1, await 2, await 3])();
  console.timeEnd('await');
  return result;
})();
```

Why would `await 1` ever need to create a micro task, if already executed
into a scheduled one via async?

Or in general, why any callback that would early return a value that is not
a promise should create a micro task?

So the proposal was implemented in an attempt to de-sugar `await?` into the
steps proposed by the dev I've interacted with:

```js
const value = await? callback();

// as sugar for
let value = callback();
if ('then' in value)
  value = await value;
```

The order is guaranteed and linear in every case, so that nothing actually
change logically speaking, and the hint would be about performance, 'cause
engines don't apparently optimize non-promise based cases.

However, since the initial intent/proposal about performance got translated
into everything else, I've instantly lost interest myself as it's evident
an `await?` would causes more confusion than it solves.

I am also not answering other points as not relevant for this idea/proposal.

Thanks regardless for sharing your thoughts, it helped me see it would
confuse developers.

Best Regards





On Tue, Oct 8, 2019 at 11:58 PM Dan Peddle  wrote:

> Have to agree, mixing sync and async code like this looks like a disaster
> waiting to happen. Knowing which order your code will be executed in might
> seem not so important for controlled environments where micro optimisations
> are attractive, but thinking about trying to track down a bug through this
> would drive me nuts.
>
> Imagine you have a cached value which can be retrieved synchronously -
> other code which runs in order, and perhaps not directly part of this
> chain, would be fine. When it’s not there, zalgo would indeed be released.
> The solution to this is to use promises (as I’m sure you know) so you have
> a consistent way of saying when something is ready... otherwise it’s
> thenable sniffing all the way through the codebase.
>
> Async infers some kind of IO or deferred process, scheduling. If there’s a
> dependency, then we need to express that. That it may be in some cases
> available synchronously seems like something to be extremely wary of.
>
> > On 8. Oct 2019, at 22:25, Tab Atkins Jr.  wrote:
> >
> > I'm not sure I understand the intended use-case here.  If the author
> > knows the function they're calling is async, they can use `await`
> > normally. If they know it's not async, they can avoid `await`
> > altogether. If they have no idea whether it's async or not, that means
> > they just don't understand what the function is returning, which
> > sounds like a really bad thing that they should fix?  And in that
> > case, as Gus says, `await?`'s semantics would do some confusing things
> > to execution order, making the line after the `await?` either run
> > *before* or *after* the calling code, depending on whether the await'd
> > value was a promise or not.
> >
> > ~TJ
> > ___
> > es-discuss mailing list
> > es-discuss@mozilla.org
> > https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-08 Thread Dan Peddle
Have to agree, mixing sync and async code like this looks like a disaster 
waiting to happen. Knowing which order your code will be executed in might seem 
not so important for controlled environments where micro optimisations are 
attractive, but thinking about trying to track down a bug through this would 
drive me nuts.

Imagine you have a cached value which can be retrieved synchronously - other 
code which runs in order, and perhaps not directly part of this chain, would be 
fine. When it’s not there, zalgo would indeed be released. The solution to this 
is to use promises (as I’m sure you know) so you have a consistent way of 
saying when something is ready... otherwise it’s thenable sniffing all the way 
through the codebase. 

Async infers some kind of IO or deferred process, scheduling. If there’s a 
dependency, then we need to express that. That it may be in some cases 
available synchronously seems like something to be extremely wary of.

> On 8. Oct 2019, at 22:25, Tab Atkins Jr.  wrote:
> 
> I'm not sure I understand the intended use-case here.  If the author
> knows the function they're calling is async, they can use `await`
> normally. If they know it's not async, they can avoid `await`
> altogether. If they have no idea whether it's async or not, that means
> they just don't understand what the function is returning, which
> sounds like a really bad thing that they should fix?  And in that
> case, as Gus says, `await?`'s semantics would do some confusing things
> to execution order, making the line after the `await?` either run
> *before* or *after* the calling code, depending on whether the await'd
> value was a promise or not.
> 
> ~TJ
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-08 Thread Tab Atkins Jr.
I'm not sure I understand the intended use-case here.  If the author
knows the function they're calling is async, they can use `await`
normally. If they know it's not async, they can avoid `await`
altogether. If they have no idea whether it's async or not, that means
they just don't understand what the function is returning, which
sounds like a really bad thing that they should fix?  And in that
case, as Gus says, `await?`'s semantics would do some confusing things
to execution order, making the line after the `await?` either run
*before* or *after* the calling code, depending on whether the await'd
value was a promise or not.

~TJ
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-08 Thread Gus Caplan
> Sure thing, engines might infer returned values in some hot code and skip
the microtask dance once it's sure some callback might return values that
are not promises, but what if developers could give hints about this
possibility?

Engines can't do this, because it would change the observable order of
running code.

> so ... how about accepting a question mark after `await` so that it's
clear the developer knows the function might return non Promise based
results, hence the code could be faster?

This is actually considered an antipattern (google "zalgo javascript"), and
promises try to stop that from happening.

On Tue, Oct 8, 2019 at 10:34 AM Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> When developers use `async` functions, they'll likely also await
> unconditionally any callback, even if such callback could return a non
> promise value, for whatever reason.
>
> Engines are great at optimizing stuff, but as of today, if we measure the
> performance difference between this code:
>
> ```js
> (async () => {
>   console.time('await');
>   const result = await (async () => [await 1, await 2, await 3])();
>   console.timeEnd('await');
>   return result;
> })();
> ```
>
> and the following one:
>
> ```js
> (/* sync */ () => {
>   console.time('sync');
>   const result = (() => [1, 2, 3])();
>   console.timeEnd('sync');
>   return result;
> })();
> ```
>
> we'll notice the latter is about 10 to 100 times faster than the
> asynchronous one.
>
> Sure thing, engines might infer returned values in some hot code and skip
> the microtask dance once it's sure some callback might return values that
> are not promises, but what if developers could give hints about this
> possibility?
>
> In a twitter exchange, one dev mentioned the following:
>
> > I often write:
> > let value = mightBePromise()
> > if (value && value.then)
> >   value = await value
> > in hot code in my async functions, for precisely this reason (I too have
> measured the large perf difference).
>
> so ... how about accepting a question mark after `await` so that it's
> clear the developer knows the function might return non Promise based
> results, hence the code could be faster?
>
> ```js
> const value = await? callback();
> ```
>
> Above code is basically what's this thread/proposal about, adding a
> conditional `await` syntax, so that if the returned value is not thenable,
> there's no reason to waste a microtask on it.
>
> What are your thoughts?
>
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss