Precedence of yield operator

classic Classic list List threaded Threaded
22 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Precedence of yield operator

Bruno Jouhier
While playing with my little async/await library, I noticed that I was often forced to parenthesize yield expressions as (yield exp) because of the low precedence of the yield operator. Typical patterns are:

var foo = (yield a()) + (yield b()) + (yield c());
if ((yield a()) && cond2 ...) ...

Looks more LISPish than JSish to me.

The low precedence plays well with yield _statements_, as it lets you write
  yield a + b;
very much like you would write
  return a + b;

But it does not play as well with yield _expressions_.

The only solutions I can think of would be to have a different keyword for yield _expressions_ (await?) with the same precedence as other unary operators.

Anyway, this is only a small annoyance and I know it's getting late into the game. But I thought I'd raise the issue anyway.

Bruno

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Precedence of yield operator

Tab Atkins Jr.
On Fri, Jun 14, 2013 at 5:12 PM, Bruno Jouhier <[hidden email]> wrote:

> While playing with my little async/await library, I noticed that I was often
> forced to parenthesize yield expressions as (yield exp) because of the low
> precedence of the yield operator. Typical patterns are:
>
> var foo = (yield a()) + (yield b()) + (yield c());
> if ((yield a()) && cond2 ...) ...
>
> Looks more LISPish than JSish to me.
>
> The low precedence plays well with yield _statements_, as it lets you write
>   yield a + b;
> very much like you would write
>   return a + b;
>
> But it does not play as well with yield _expressions_.
>
> The only solutions I can think of would be to have a different keyword for
> yield _expressions_ (await?) with the same precedence as other unary
> operators.
>
> Anyway, this is only a small annoyance and I know it's getting late into the
> game. But I thought I'd raise the issue anyway.

Using generators for async is a clever hack, but it's just a hack.  A
proper solution will need a new keyword anyway (most languages seem to
use "await" or something similar), which can get the better
precedence.

~TJ
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Precedence of yield operator

Sam Tobin-Hochstadt
On Fri, Jun 14, 2013 at 11:21 AM, Tab Atkins Jr. <[hidden email]> wrote:
> Using generators for async is a clever hack, but it's just a hack.  A
> proper solution will need a new keyword anyway (most languages seem to
> use "await" or something similar), which can get the better
> precedence.

This is just not true -- the semantics of generators and of `await` as
proposed on this list are very very similar.

Sam
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Precedence of yield operator

Tab Atkins Jr.
On Fri, Jun 14, 2013 at 5:33 PM, Sam Tobin-Hochstadt <[hidden email]> wrote:
> On Fri, Jun 14, 2013 at 11:21 AM, Tab Atkins Jr. <[hidden email]> wrote:
>> Using generators for async is a clever hack, but it's just a hack.  A
>> proper solution will need a new keyword anyway (most languages seem to
>> use "await" or something similar), which can get the better
>> precedence.
>
> This is just not true -- the semantics of generators and of `await` as
> proposed on this list are very very similar.

Yup, very similar, but not identical, which is why we have slight
incompatibilities in the desired precedence, why you need to have a
wrapper to handle the calling, etc.

~TJ
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Precedence of yield operator

Brendan Eich-3
In reply to this post by Bruno Jouhier
Bruno Jouhier wrote:
> While playing with my little async/await library, I noticed that I was
> often forced to parenthesize yield expressions as (yield exp) because
> of the low precedence of the yield operator. Typical patterns are:
>
> var foo = (yield a()) + (yield b()) + (yield c());

That's actually a hard case, IMHO -- and "hard cases make bad law".

Many programmers would rather have the extra parens for uncertain cases
(C's misplaced bitwise-logical and shift operators, vs.
equality/relational; anything novel such as yield).

But the real reason for yield being low precedence is to avoid
precedence inversion. Consider if yield could be high-precedence, say a
unary operator like delete:

let x = yield a + b;

Oops, many people would want that to be equivalent to

let x = yield (a + b);

but if yield is at delete's precence level, it's rather:

let x = (yield a) + b;

Which is the rare ("hard", from law school) case.

For commutative operators such as +, over-parenthesizing is better
again, because

let x = b + (yield a);

and

let x = (yield a) + b;

ignoring order of effects in shared mutable store, and ignoring floating
point non-determinism, are equivalent.

/be
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Precedence of yield operator

Bruno Jouhier
The current precedence looks natural to me for a yield but less when yield is used as an await keyword.  That's why I proposed to handle it with a different keyword rather than by changing yield's precedence. Await would have been a good candidate but it is not reserved.

Anyway, I don't want to make a big fuss about it. That's just something I noticed while writing examples of async code with generators. Adding the parentheses is not such a big deal.


2013/6/14 Brendan Eich <[hidden email]>
Bruno Jouhier wrote:
While playing with my little async/await library, I noticed that I was often forced to parenthesize yield expressions as (yield exp) because of the low precedence of the yield operator. Typical patterns are:

var foo = (yield a()) + (yield b()) + (yield c());

That's actually a hard case, IMHO -- and "hard cases make bad law".

Many programmers would rather have the extra parens for uncertain cases (C's misplaced bitwise-logical and shift operators, vs. equality/relational; anything novel such as yield).

But the real reason for yield being low precedence is to avoid precedence inversion. Consider if yield could be high-precedence, say a unary operator like delete:

let x = yield a + b;

Oops, many people would want that to be equivalent to

let x = yield (a + b);

but if yield is at delete's precence level, it's rather:

let x = (yield a) + b;

Which is the rare ("hard", from law school) case.

For commutative operators such as +, over-parenthesizing is better again, because

let x = b + (yield a);

and

let x = (yield a) + b;

ignoring order of effects in shared mutable store, and ignoring floating point non-determinism, are equivalent.

/be


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Precedence of yield operator

Dean Tribble-2
In reply to this post by Brendan Eich-3
This is a familiar discussion from C#. I forwarded it to the mediator of that convresation and got a nice summary, pasted here:

---------- Forwarded message ----------
From: Mads Torgersen <[hidden email]>
Date: Fri, Jun 14, 2013 at 2:11 PM
Subject: RE: Precedence of yield operator
To: Dean Tribble <[hidden email]>


I’m not on the mailing list. Feel free to forward to it.

 

In C# we have separate keywords too, and indeed the precedence differs as described below. For “yield return” (our yield) the lower precendence falls out naturally since it engenders a statement, not an expression.                                                                                                                         

 “await” is not a reserved keyword in C# either, but we managed to wedge it in all the same. Just adding await as an operator would lead to all kinds of ambiguity; e.g. “await (x)” could be a function call or an await expression, and the statement “await x;” could be a variable declaration or an await statement.

 

However, in C# “await” is only allowed inside methods marked “async”, and since there weren’t any of those around before the feature was introduced, it is not a breaking change. Inside non-async methods, therefore, “await” continues to be just an identifier.

 

I don’t know if a similar thing is possible in EcmaScript. But I believe that a low-precedence yield as a substitute for a high-precedence await is problematic: you never want “yield a + yield b” to mean “yield (a + (yield b))”: the things you await – Task, Promises, Futures, whatever you call them – just don’t have operators defined on them, and it would be silly to parse them as if they might and then give errors (at runtime in EcmaScript, at compile time in e.g. TypeScript).

 

Mads


On Fri, Jun 14, 2013 at 11:07 AM, Brendan Eich <[hidden email]> wrote:
Bruno Jouhier wrote:
While playing with my little async/await library, I noticed that I was often forced to parenthesize yield expressions as (yield exp) because of the low precedence of the yield operator. Typical patterns are:

var foo = (yield a()) + (yield b()) + (yield c());

That's actually a hard case, IMHO -- and "hard cases make bad law".

Many programmers would rather have the extra parens for uncertain cases (C's misplaced bitwise-logical and shift operators, vs. equality/relational; anything novel such as yield).

But the real reason for yield being low precedence is to avoid precedence inversion. Consider if yield could be high-precedence, say a unary operator like delete:

let x = yield a + b;

Oops, many people would want that to be equivalent to

let x = yield (a + b);

but if yield is at delete's precence level, it's rather:

let x = (yield a) + b;

Which is the rare ("hard", from law school) case.

For commutative operators such as +, over-parenthesizing is better again, because

let x = b + (yield a);

and

let x = (yield a) + b;

ignoring order of effects in shared mutable store, and ignoring floating point non-determinism, are equivalent.

/be

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


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Fwd: Precedence of yield operator

Bruno Jouhier

I don’t know if a similar thing is possible in EcmaScript. But I believe that a low-precedence yield as a substitute for a high-precedence await is problematic: you never want “yield a + yield b” to mean “yield (a + (yield b))”: the things you await – Task, Promises, Futures, whatever you call them – just don’t have operators defined on them, and it would be silly to parse them as if they might and then give errors (at runtime in EcmaScript, at compile time in e.g. TypeScript).


This is exactly the problem I ran into: yield does the job of await but the syntax rule feels a bit silly.

This is not too dramatic because the errors are either detected at compile time (yield a + yield b) or at runtime by my little library (yield a + b).


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Precedence of yield operator

Brendan Eich-3
In reply to this post by Dean Tribble-2
This is all on the agenda for ES7. It cleanly missed ES6 in May 2011(!).

https://mail.mozilla.org/pipermail/es-discuss/2011-May/014748.html

/be

Dean Tribble wrote:

> This is a familiar discussion from C#. I forwarded it to the mediator
> of that convresation and got a nice summary, pasted here:
>
> ---------- Forwarded message ----------
> From: *Mads Torgersen* <[hidden email]
> <mailto:[hidden email]>>
> Date: Fri, Jun 14, 2013 at 2:11 PM
> Subject: RE: Precedence of yield operator
> To: Dean Tribble <[hidden email] <mailto:[hidden email]>>
>
>
> I’m not on the mailing list. Feel free to forward to it.
>
> In C# we have separate keywords too, and indeed the precedence differs
> as described below. For “yield return” (our yield) the lower
> precendence falls out naturally since it engenders a statement, not an
> expression.
>
> “await” is not a reserved keyword in C# either, but we managed to
> wedge it in all the same. Just adding await as an operator would lead
> to all kinds of ambiguity; e.g. “await (x)” could be a function call
> or an await expression, and the statement “await x;” could be a
> variable declaration or an await statement.
>
> However, in C# “await” is only allowed inside methods marked “async”,
> and since there weren’t any of those around before the feature was
> introduced, it is not a breaking change. Inside non-async methods,
> therefore, “await” continues to be just an identifier.
>
> I don’t know if a similar thing is possible in EcmaScript. But I
> believe that a low-precedence yield as a substitute for a
> high-precedence await is problematic: you never want “yield a + yield
> b” to mean “yield (a + (yield b))”: the things you await – Task,
> Promises, Futures, whatever you call them – just don’t have operators
> defined on them, and it would be silly to parse them as if they might
> and then give errors (at runtime in EcmaScript, at compile time in
> e.g. TypeScript).
>
> Mads
>
>
> On Fri, Jun 14, 2013 at 11:07 AM, Brendan Eich <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     Bruno Jouhier wrote:
>
>         While playing with my little async/await library, I noticed
>         that I was often forced to parenthesize yield expressions as
>         (yield exp) because of the low precedence of the yield
>         operator. Typical patterns are:
>
>         var foo = (yield a()) + (yield b()) + (yield c());
>
>
>     That's actually a hard case, IMHO -- and "hard cases make bad law".
>
>     Many programmers would rather have the extra parens for uncertain
>     cases (C's misplaced bitwise-logical and shift operators, vs.
>     equality/relational; anything novel such as yield).
>
>     But the real reason for yield being low precedence is to avoid
>     precedence inversion. Consider if yield could be high-precedence,
>     say a unary operator like delete:
>
>     let x = yield a + b;
>
>     Oops, many people would want that to be equivalent to
>
>     let x = yield (a + b);
>
>     but if yield is at delete's precence level, it's rather:
>
>     let x = (yield a) + b;
>
>     Which is the rare ("hard", from law school) case.
>
>     For commutative operators such as +, over-parenthesizing is better
>     again, because
>
>     let x = b + (yield a);
>
>     and
>
>     let x = (yield a) + b;
>
>     ignoring order of effects in shared mutable store, and ignoring
>     floating point non-determinism, are equivalent.
>
>     /be
>
>     _______________________________________________
>     es-discuss mailing list
>     [hidden email] <mailto:[hidden email]>
>     https://mail.mozilla.org/listinfo/es-discuss
>
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Precedence of yield operator

François REMY-2
I'm maybe biased, but I would love to consider "yield" as a function.
Indeed, it calls another code, which can return you a value. That looks very
similar to a function call to me. If we do this, the predecence becomes
intuitive again:

    var x = yield(a) + yield(b);
    yield(a+b);

I think there was a proposal to allow parenthesis-free function call at some
point at the root of a statement. When it lands, you'll be able to do things
like

    yield a+b;

as a normal statement again. In the mean time we can just use parentheses,
that's not a huge issue and it helps clarity.



But maybe this is too late to change ES6, it's just an idea I had while
reading this thread, not a strong call for change.






-----Message d'origine-----
From: Brendan Eich
Sent: Saturday, June 15, 2013 6:17 AM
To: Dean Tribble
Cc: Bruno Jouhier ; [hidden email]
Subject: Re: Precedence of yield operator

This is all on the agenda for ES7. It cleanly missed ES6 in May 2011(!).

https://mail.mozilla.org/pipermail/es-discuss/2011-May/014748.html

/be

Dean Tribble wrote:

> This is a familiar discussion from C#. I forwarded it to the mediator of
> that convresation and got a nice summary, pasted here:
>
> ---------- Forwarded message ----------
> From: *Mads Torgersen* <[hidden email]
> <mailto:[hidden email]>>
> Date: Fri, Jun 14, 2013 at 2:11 PM
> Subject: RE: Precedence of yield operator
> To: Dean Tribble <[hidden email] <mailto:[hidden email]>>
>
>
> I’m not on the mailing list. Feel free to forward to it.
>
> In C# we have separate keywords too, and indeed the precedence differs as
> described below. For “yield return” (our yield) the lower precendence
> falls out naturally since it engenders a statement, not an expression.
>
> “await” is not a reserved keyword in C# either, but we managed to wedge it
> in all the same. Just adding await as an operator would lead to all kinds
> of ambiguity; e.g. “await (x)” could be a function call or an await
> expression, and the statement “await x;” could be a variable declaration
> or an await statement.
>
> However, in C# “await” is only allowed inside methods marked “async”, and
> since there weren’t any of those around before the feature was introduced,
> it is not a breaking change. Inside non-async methods, therefore, “await”
> continues to be just an identifier.
>
> I don’t know if a similar thing is possible in EcmaScript. But I believe
> that a low-precedence yield as a substitute for a high-precedence await is
> problematic: you never want “yield a + yield b” to mean “yield (a + (yield
> b))”: the things you await – Task, Promises, Futures, whatever you call
> them – just don’t have operators defined on them, and it would be silly to
> parse them as if they might and then give errors (at runtime in
> EcmaScript, at compile time in e.g. TypeScript).
>
> Mads
>
>
> On Fri, Jun 14, 2013 at 11:07 AM, Brendan Eich <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     Bruno Jouhier wrote:
>
>         While playing with my little async/await library, I noticed
>         that I was often forced to parenthesize yield expressions as
>         (yield exp) because of the low precedence of the yield
>         operator. Typical patterns are:
>
>         var foo = (yield a()) + (yield b()) + (yield c());
>
>
>     That's actually a hard case, IMHO -- and "hard cases make bad law".
>
>     Many programmers would rather have the extra parens for uncertain
>     cases (C's misplaced bitwise-logical and shift operators, vs.
>     equality/relational; anything novel such as yield).
>
>     But the real reason for yield being low precedence is to avoid
>     precedence inversion. Consider if yield could be high-precedence,
>     say a unary operator like delete:
>
>     let x = yield a + b;
>
>     Oops, many people would want that to be equivalent to
>
>     let x = yield (a + b);
>
>     but if yield is at delete's precence level, it's rather:
>
>     let x = (yield a) + b;
>
>     Which is the rare ("hard", from law school) case.
>
>     For commutative operators such as +, over-parenthesizing is better
>     again, because
>
>     let x = b + (yield a);
>
>     and
>
>     let x = (yield a) + b;
>
>     ignoring order of effects in shared mutable store, and ignoring
>     floating point non-determinism, are equivalent.
>
>     /be
>
>     _______________________________________________
>     es-discuss mailing list
>     [hidden email] <mailto:[hidden email]>
>     https://mail.mozilla.org/listinfo/es-discuss
>
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss 

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Precedence of yield operator

Bruno Jouhier
If this is on the agenda for ES7 maybe ES6 should at least reserve "await" as a keyword in function* scopes.


2013/6/15 François REMY <[hidden email]>
I'm maybe biased, but I would love to consider "yield" as a function. Indeed, it calls another code, which can return you a value. That looks very similar to a function call to me. If we do this, the predecence becomes intuitive again:

   var x = yield(a) + yield(b);
   yield(a+b);

I think there was a proposal to allow parenthesis-free function call at some point at the root of a statement. When it lands, you'll be able to do things like

   yield a+b;

as a normal statement again. In the mean time we can just use parentheses, that's not a huge issue and it helps clarity.



But maybe this is too late to change ES6, it's just an idea I had while reading this thread, not a strong call for change.






-----Message d'origine----- From: Brendan Eich
Sent: Saturday, June 15, 2013 6:17 AM
To: Dean Tribble
Cc: Bruno Jouhier ; [hidden email]
Subject: Re: Precedence of yield operator


This is all on the agenda for ES7. It cleanly missed ES6 in May 2011(!).

https://mail.mozilla.org/pipermail/es-discuss/2011-May/014748.html

/be

Dean Tribble wrote:
This is a familiar discussion from C#. I forwarded it to the mediator of that convresation and got a nice summary, pasted here:

---------- Forwarded message ----------
From: *Mads Torgersen* <[hidden email] <mailto:[hidden email]>>
Date: Fri, Jun 14, 2013 at 2:11 PM
Subject: RE: Precedence of yield operator
To: Dean Tribble <[hidden email] <mailto:[hidden email]>>


I’m not on the mailing list. Feel free to forward to it.

In C# we have separate keywords too, and indeed the precedence differs as described below. For “yield return” (our yield) the lower precendence falls out naturally since it engenders a statement, not an expression.

“await” is not a reserved keyword in C# either, but we managed to wedge it in all the same. Just adding await as an operator would lead to all kinds of ambiguity; e.g. “await (x)” could be a function call or an await expression, and the statement “await x;” could be a variable declaration or an await statement.

However, in C# “await” is only allowed inside methods marked “async”, and since there weren’t any of those around before the feature was introduced, it is not a breaking change. Inside non-async methods, therefore, “await” continues to be just an identifier.

I don’t know if a similar thing is possible in EcmaScript. But I believe that a low-precedence yield as a substitute for a high-precedence await is problematic: you never want “yield a + yield b” to mean “yield (a + (yield b))”: the things you await – Task, Promises, Futures, whatever you call them – just don’t have operators defined on them, and it would be silly to parse them as if they might and then give errors (at runtime in EcmaScript, at compile time in e.g. TypeScript).

Mads


On Fri, Jun 14, 2013 at 11:07 AM, Brendan Eich <[hidden email] <mailto:[hidden email]>> wrote:

    Bruno Jouhier wrote:

        While playing with my little async/await library, I noticed
        that I was often forced to parenthesize yield expressions as
        (yield exp) because of the low precedence of the yield
        operator. Typical patterns are:

        var foo = (yield a()) + (yield b()) + (yield c());


    That's actually a hard case, IMHO -- and "hard cases make bad law".

    Many programmers would rather have the extra parens for uncertain
    cases (C's misplaced bitwise-logical and shift operators, vs.
    equality/relational; anything novel such as yield).

    But the real reason for yield being low precedence is to avoid
    precedence inversion. Consider if yield could be high-precedence,
    say a unary operator like delete:

    let x = yield a + b;

    Oops, many people would want that to be equivalent to

    let x = yield (a + b);

    but if yield is at delete's precence level, it's rather:

    let x = (yield a) + b;

    Which is the rare ("hard", from law school) case.

    For commutative operators such as +, over-parenthesizing is better
    again, because

    let x = b + (yield a);

    and

    let x = (yield a) + b;

    ignoring order of effects in shared mutable store, and ignoring
    floating point non-determinism, are equivalent.

    /be

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


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


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Precedence of yield operator

Claude Pache
In reply to this post by François REMY-2


Le 15 juin 2013 à 10:18, François REMY <[hidden email]> a écrit :

> I'm maybe biased, but I would love to consider "yield" as a function. Indeed, it calls another code, which can return you a value. That looks very similar to a function call to me. If we do this, the predecence becomes intuitive again:
>
>   var x = yield(a) + yield(b);
>   yield(a+b);
>
> I think there was a proposal to allow parenthesis-free function call at some point at the root of a statement. When it lands, you'll be able to do things like
>
>   yield a+b;
>
> as a normal statement again. In the mean time we can just use parentheses, that's not a huge issue and it helps clarity.
>
>
>
> But maybe this is too late to change ES6, it's just an idea I had while reading this thread, not a strong call for change.
>

There is an issue when the argument of an intended parenthesis-free function call happens to begin with a parenthesis:

    yield a*(b + c)    <==>    yield(a*(b + c))
    yield (b + c)*a    <==>    (yield(b + c))*a    instead of     yield((b + c) *a)

—Claude

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Precedence of yield operator

François REMY-2
> There is an issue when the argument of an
> intended parenthesis-free function call
> happens to begin with a parenthesis.

Just like there are issues if you want to return an object literal from a
lambda in JS, you've to use parentheses around it. Not a big deal.

Anyway, I'm not saying we should support paren-free function calls, I'm just
saying that if we ever do, that would also apply to the "yield
pseudo-function" of my proposal, too.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Precedence of yield operator

Mark S. Miller-2
In reply to this post by Bruno Jouhier
If we do provide such special syntax, then I suggest (a variant on some else's suggestion -- I forget who) that "yield" is to "function* as "await" is to "function!", amplifying the association of "!" with asynchrony. Rather than say "async function" or whatever, we'd just say "function!". Since "function!" would be new in ES7, there's no reason to reserve anything in ES6 to prepare for this.



On Sat, Jun 15, 2013 at 2:40 AM, Bruno Jouhier <[hidden email]> wrote:
If this is on the agenda for ES7 maybe ES6 should at least reserve "await" as a keyword in function* scopes.


2013/6/15 François REMY <[hidden email]>
I'm maybe biased, but I would love to consider "yield" as a function. Indeed, it calls another code, which can return you a value. That looks very similar to a function call to me. If we do this, the predecence becomes intuitive again:

   var x = yield(a) + yield(b);
   yield(a+b);

I think there was a proposal to allow parenthesis-free function call at some point at the root of a statement. When it lands, you'll be able to do things like

   yield a+b;

as a normal statement again. In the mean time we can just use parentheses, that's not a huge issue and it helps clarity.



But maybe this is too late to change ES6, it's just an idea I had while reading this thread, not a strong call for change.






-----Message d'origine----- From: Brendan Eich
Sent: Saturday, June 15, 2013 6:17 AM
To: Dean Tribble
Cc: Bruno Jouhier ; [hidden email]
Subject: Re: Precedence of yield operator


This is all on the agenda for ES7. It cleanly missed ES6 in May 2011(!).

https://mail.mozilla.org/pipermail/es-discuss/2011-May/014748.html

/be

Dean Tribble wrote:
This is a familiar discussion from C#. I forwarded it to the mediator of that convresation and got a nice summary, pasted here:

---------- Forwarded message ----------
From: *Mads Torgersen* <[hidden email] <mailto:[hidden email]>>
Date: Fri, Jun 14, 2013 at 2:11 PM
Subject: RE: Precedence of yield operator
To: Dean Tribble <[hidden email] <mailto:[hidden email]>>


I’m not on the mailing list. Feel free to forward to it.

In C# we have separate keywords too, and indeed the precedence differs as described below. For “yield return” (our yield) the lower precendence falls out naturally since it engenders a statement, not an expression.

“await” is not a reserved keyword in C# either, but we managed to wedge it in all the same. Just adding await as an operator would lead to all kinds of ambiguity; e.g. “await (x)” could be a function call or an await expression, and the statement “await x;” could be a variable declaration or an await statement.

However, in C# “await” is only allowed inside methods marked “async”, and since there weren’t any of those around before the feature was introduced, it is not a breaking change. Inside non-async methods, therefore, “await” continues to be just an identifier.

I don’t know if a similar thing is possible in EcmaScript. But I believe that a low-precedence yield as a substitute for a high-precedence await is problematic: you never want “yield a + yield b” to mean “yield (a + (yield b))”: the things you await – Task, Promises, Futures, whatever you call them – just don’t have operators defined on them, and it would be silly to parse them as if they might and then give errors (at runtime in EcmaScript, at compile time in e.g. TypeScript).

Mads


On Fri, Jun 14, 2013 at 11:07 AM, Brendan Eich <[hidden email] <mailto:[hidden email]>> wrote:

    Bruno Jouhier wrote:

        While playing with my little async/await library, I noticed
        that I was often forced to parenthesize yield expressions as
        (yield exp) because of the low precedence of the yield
        operator. Typical patterns are:

        var foo = (yield a()) + (yield b()) + (yield c());


    That's actually a hard case, IMHO -- and "hard cases make bad law".

    Many programmers would rather have the extra parens for uncertain
    cases (C's misplaced bitwise-logical and shift operators, vs.
    equality/relational; anything novel such as yield).

    But the real reason for yield being low precedence is to avoid
    precedence inversion. Consider if yield could be high-precedence,
    say a unary operator like delete:

    let x = yield a + b;

    Oops, many people would want that to be equivalent to

    let x = yield (a + b);

    but if yield is at delete's precence level, it's rather:

    let x = (yield a) + b;

    Which is the rare ("hard", from law school) case.

    For commutative operators such as +, over-parenthesizing is better
    again, because

    let x = b + (yield a);

    and

    let x = (yield a) + b;

    ignoring order of effects in shared mutable store, and ignoring
    floating point non-determinism, are equivalent.

    /be

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


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


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




--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Precedence of yield operator

Rick Waldron


On Saturday, June 15, 2013, Mark S. Miller wrote:
If we do provide such special syntax, then I suggest (a variant on some else's suggestion -- I forget who) that "yield" is to "function* as "await" is to "function!", amplifying the association of "!" with asynchrony. Rather than say "async function" or whatever, we'd just say "function!". Since "function!" would be new in ES7, there's no reason to reserve anything in ES6 to prepare for this.

Mark, is there a particular rationale for the reuse of "!" as the eventual send operator and here for similar semantics? I recall this also appeared in you Distributed Electronic Rights paper. Putting its strong existing meaning aside (negation), when I see "!" I think of "urgent" things—quite the opposite of the behavior described in the paper and above.

Rick


 




On Sat, Jun 15, 2013 at 2:40 AM, Bruno Jouhier <[hidden email]> wrote:
If this is on the agenda for ES7 maybe ES6 should at least reserve "await" as a keyword in function* scopes.


2013/6/15 François REMY <[hidden email]>
I'm maybe biased, but I would love to consider "yield" as a function. Indeed, it calls another code, which can return you a value. That looks very similar to a function call to me. If we do this, the predecence becomes intuitive again:

   var x = yield(a) + yield(b);
   yield(a+b);

I think there was a proposal to allow parenthesis-free function call at some point at the root of a statement. When it lands, you'll be able to do things like

   yield a+b;

as a normal statement again. In the mean time we can just use parentheses, that's not a huge issue and it helps clarity.



But maybe this is too late to change ES6, it's just an idea I had while reading this thread, not a strong call for change.






-----Message d'origine----- From: Brendan Eich
Sent: Saturday, June 15, 2013 6:17 AM
To: Dean Tribble
Cc: Bruno Jouhier ; [hidden email]
Subject: Re: Precedence of yield operator


This is all on the agenda for ES7. It cleanly missed ES6 in May 2011(!).

https://mail.mozilla.org/pipermail/es-discuss/2011-May/014748.html

/be

Dean Tribble wrote:
This is a familiar discussion from C#. I forwarded it to the mediator of that convresation and got a nice summary, pasted here:

---------- Forwarded message ----------
From: *Mads Torgersen* <[hidden email] <mailto:Mads.Torgersen@microsoft.com>>
Date: Fri, Jun 14, 2013 at 2:11 PM
Subject: RE: Precedence of yield operator
To: Dean Tribble <[hidden email] <mailto:[hidden email]>>


I’m not on the mailing list. Feel free to forward to it.

In C# we have separate keywords too, and indeed the precedence differs as described below. For “yield return” (our yield) the lower precendence falls out naturally since it engenders a statement, not an expression.

“await” is not a reserved keyword in C# either, but we managed to wedge it in all the same. Just adding await as an operator would lead to all kinds of ambiguity; e.g. “await (x)” could be a function call or an await expression, and the statement “await x;” could be a variable declaration or an await statement.

However, in C# “await” is only allowed inside methods marked “async”, and since there weren’t any of those around before the feature was introduced, it is not a breaking change. Inside non-async methods, therefore, “await” continues to be just an identifier.

I don’t know if a similar thing is possible in EcmaScript. But I believe that a low-precedence yield as a substitute for a high-precedence await is problematic: you never want “yield a + yield b” to mean “yield (a + (yield b))”: the things you await – Task, Promises, Futures, whatever you call them – just don’t have operators defined on them, and it would be silly to parse them as if they might and then give errors (at runtime in EcmaScript, at compile time in e.g. TypeScript).

Mads


On Fri, Jun 14, 2013 at 11:07 AM, Brendan Eich <[hidden email] <mailto:[hidden email]>> wrote:

    Bruno Jouhier wrote:

        While playing with my little async/await library, I noticed
--
    Cheers,
    --MarkM
 

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Precedence of yield operator

Mark S. Miller-2
I hadn't thought of the "urgent" implication -- interesting. I agree that this has the contrary connotations which is unfortunate.

E and AmbientTalk use "<-" which I always thought read well. In E, the "then" concept is named "when" and is also supported as a syntactic form using the "-> syntax. These work well together, as both indicate asynchrony, with the direction of the arrow indicating what is eventually being delivered to what.

In JS, "a <- b" already parses as "a < -b" so introducing a "<-" token is a non-starter. Process calculi languages like Pict (based on Pi Calculus), and languages inspired by process calculi notions like Erlang and Scala use an infix "!" for message sending, with the receiver on the left and the payload on the right. This started with Tony Hoare's CSP (Communicating Sequential Processes) and was picked up by Occam, where it was synchronous. Technically it is synchronous in the Pi Calculus too. But in Pict, Erlang, and Scala it is asynchronous. (Pict is based on the asynchronous subset of the Pi Calculus.)

More importantly for our audience, for JS (and similarly for Scala), there's also a nice mnemonic rule: Wherever you can write an infix "." you can write an infix "!" instead, changing the meaning of the construct from synchronous to asynchronous. The "!" symbol has a "." at the bottom of it, so you can think of it as "an enhanced dot" or even "a dot with a trail" if you'd like.

In any case, once the eye gets used to it the need for these mnemonics rapidly drops away. Having lived with both "<-" and "!", I've come to prefer the "!". I'm not really sure why.




On Sat, Jun 15, 2013 at 7:23 PM, Rick Waldron <[hidden email]> wrote:


On Saturday, June 15, 2013, Mark S. Miller wrote:
If we do provide such special syntax, then I suggest (a variant on some else's suggestion -- I forget who) that "yield" is to "function* as "await" is to "function!", amplifying the association of "!" with asynchrony. Rather than say "async function" or whatever, we'd just say "function!". Since "function!" would be new in ES7, there's no reason to reserve anything in ES6 to prepare for this.

Mark, is there a particular rationale for the reuse of "!" as the eventual send operator and here for similar semantics? I recall this also appeared in you Distributed Electronic Rights paper. Putting its strong existing meaning aside (negation), when I see "!" I think of "urgent" things—quite the opposite of the behavior described in the paper and above.

Rick


 




On Sat, Jun 15, 2013 at 2:40 AM, Bruno Jouhier <[hidden email]> wrote:
If this is on the agenda for ES7 maybe ES6 should at least reserve "await" as a keyword in function* scopes.


2013/6/15 François REMY <[hidden email]>
I'm maybe biased, but I would love to consider "yield" as a function. Indeed, it calls another code, which can return you a value. That looks very similar to a function call to me. If we do this, the predecence becomes intuitive again:

   var x = yield(a) + yield(b);
   yield(a+b);

I think there was a proposal to allow parenthesis-free function call at some point at the root of a statement. When it lands, you'll be able to do things like

   yield a+b;

as a normal statement again. In the mean time we can just use parentheses, that's not a huge issue and it helps clarity.



But maybe this is too late to change ES6, it's just an idea I had while reading this thread, not a strong call for change.






-----Message d'origine----- From: Brendan Eich
Sent: Saturday, June 15, 2013 6:17 AM
To: Dean Tribble
Cc: Bruno Jouhier ; [hidden email]
Subject: Re: Precedence of yield operator


This is all on the agenda for ES7. It cleanly missed ES6 in May 2011(!).

https://mail.mozilla.org/pipermail/es-discuss/2011-May/014748.html

/be

Dean Tribble wrote:
This is a familiar discussion from C#. I forwarded it to the mediator of that convresation and got a nice summary, pasted here:

---------- Forwarded message ----------
From: *Mads Torgersen* <[hidden email] <mailto:Mads.Torgersen@microsoft.com>>
Date: Fri, Jun 14, 2013 at 2:11 PM
Subject: RE: Precedence of yield operator
To: Dean Tribble <[hidden email] <mailto:[hidden email]>>


I’m not on the mailing list. Feel free to forward to it.

In C# we have separate keywords too, and indeed the precedence differs as described below. For “yield return” (our yield) the lower precendence falls out naturally since it engenders a statement, not an expression.

“await” is not a reserved keyword in C# either, but we managed to wedge it in all the same. Just adding await as an operator would lead to all kinds of ambiguity; e.g. “await (x)” could be a function call or an await expression, and the statement “await x;” could be a variable declaration or an await statement.

However, in C# “await” is only allowed inside methods marked “async”, and since there weren’t any of those around before the feature was introduced, it is not a breaking change. Inside non-async methods, therefore, “await” continues to be just an identifier.

I don’t know if a similar thing is possible in EcmaScript. But I believe that a low-precedence yield as a substitute for a high-precedence await is problematic: you never want “yield a + yield b” to mean “yield (a + (yield b))”: the things you await – Task, Promises, Futures, whatever you call them – just don’t have operators defined on them, and it would be silly to parse them as if they might and then give errors (at runtime in EcmaScript, at compile time in e.g. TypeScript).

Mads


On Fri, Jun 14, 2013 at 11:07 AM, Brendan Eich <[hidden email] <mailto:[hidden email]>> wrote:

    Bruno Jouhier wrote:

        While playing with my little async/await library, I noticed
--
    Cheers,
    --MarkM
 



--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Precedence of yield operator

Oliver Hunt-2
Hmmm, my initial thought was against this (and for this specific case i'm not sure i've been sold on it), but I do kind of like the concept.  Alas this is me we're talking about so I do have a few issues with it

* I'm a little concerned that this could make for easily misread code, even for other characters (! obviously disappears into line noise in english)
* Adding a new syntax for a single (though admittedly major) use case is worrying to me, i don't really want to see ES disappear into line noise territory where code changes meaning based on a single character
* It also seems a little inflexible

After reading Mark's email I did ponder what it would mean if we allowed "operators" to be described, e.g. 

function .???(...) {
   throw "Because he hates us all"
}

"This is terrible why is oliver suggesting this".???


I'm really not enamored with this, but I thought I'd throw it out here

--Oliver


On Jun 15, 2013, at 7:46 PM, "Mark S. Miller" <[hidden email]> wrote:

I hadn't thought of the "urgent" implication -- interesting. I agree that this has the contrary connotations which is unfortunate.

E and AmbientTalk use "<-" which I always thought read well. In E, the "then" concept is named "when" and is also supported as a syntactic form using the "-> syntax. These work well together, as both indicate asynchrony, with the direction of the arrow indicating what is eventually being delivered to what.

In JS, "a <- b" already parses as "a < -b" so introducing a "<-" token is a non-starter. Process calculi languages like Pict (based on Pi Calculus), and languages inspired by process calculi notions like Erlang and Scala use an infix "!" for message sending, with the receiver on the left and the payload on the right. This started with Tony Hoare's CSP (Communicating Sequential Processes) and was picked up by Occam, where it was synchronous. Technically it is synchronous in the Pi Calculus too. But in Pict, Erlang, and Scala it is asynchronous. (Pict is based on the asynchronous subset of the Pi Calculus.)

More importantly for our audience, for JS (and similarly for Scala), there's also a nice mnemonic rule: Wherever you can write an infix "." you can write an infix "!" instead, changing the meaning of the construct from synchronous to asynchronous. The "!" symbol has a "." at the bottom of it, so you can think of it as "an enhanced dot" or even "a dot with a trail" if you'd like.

In any case, once the eye gets used to it the need for these mnemonics rapidly drops away. Having lived with both "<-" and "!", I've come to prefer the "!". I'm not really sure why.




On Sat, Jun 15, 2013 at 7:23 PM, Rick Waldron <[hidden email]> wrote:


On Saturday, June 15, 2013, Mark S. Miller wrote:
If we do provide such special syntax, then I suggest (a variant on some else's suggestion -- I forget who) that "yield" is to "function* as "await" is to "function!", amplifying the association of "!" with asynchrony. Rather than say "async function" or whatever, we'd just say "function!". Since "function!" would be new in ES7, there's no reason to reserve anything in ES6 to prepare for this.

Mark, is there a particular rationale for the reuse of "!" as the eventual send operator and here for similar semantics? I recall this also appeared in you Distributed Electronic Rights paper. Putting its strong existing meaning aside (negation), when I see "!" I think of "urgent" things—quite the opposite of the behavior described in the paper and above.

Rick


 




On Sat, Jun 15, 2013 at 2:40 AM, Bruno Jouhier <[hidden email]> wrote:
If this is on the agenda for ES7 maybe ES6 should at least reserve "await" as a keyword in function* scopes.


2013/6/15 François REMY <[hidden email]>
I'm maybe biased, but I would love to consider "yield" as a function. Indeed, it calls another code, which can return you a value. That looks very similar to a function call to me. If we do this, the predecence becomes intuitive again:

   var x = yield(a) + yield(b);
   yield(a+b);

I think there was a proposal to allow parenthesis-free function call at some point at the root of a statement. When it lands, you'll be able to do things like

   yield a+b;

as a normal statement again. In the mean time we can just use parentheses, that's not a huge issue and it helps clarity.



But maybe this is too late to change ES6, it's just an idea I had while reading this thread, not a strong call for change.






-----Message d'origine----- From: Brendan Eich
Sent: Saturday, June 15, 2013 6:17 AM
To: Dean Tribble
Cc: Bruno Jouhier ; [hidden email]
Subject: Re: Precedence of yield operator


This is all on the agenda for ES7. It cleanly missed ES6 in May 2011(!).

https://mail.mozilla.org/pipermail/es-discuss/2011-May/014748.html

/be

Dean Tribble wrote:
This is a familiar discussion from C#. I forwarded it to the mediator of that convresation and got a nice summary, pasted here:

---------- Forwarded message ----------
From: *Mads Torgersen* <[hidden email] <mailto:Mads.Torgersen@microsoft.com>>
Date: Fri, Jun 14, 2013 at 2:11 PM
Subject: RE: Precedence of yield operator
To: Dean Tribble <[hidden email] <mailto:[hidden email]>>


I’m not on the mailing list. Feel free to forward to it.

In C# we have separate keywords too, and indeed the precedence differs as described below. For “yield return” (our yield) the lower precendence falls out naturally since it engenders a statement, not an expression.

“await” is not a reserved keyword in C# either, but we managed to wedge it in all the same. Just adding await as an operator would lead to all kinds of ambiguity; e.g. “await (x)” could be a function call or an await expression, and the statement “await x;” could be a variable declaration or an await statement.

However, in C# “await” is only allowed inside methods marked “async”, and since there weren’t any of those around before the feature was introduced, it is not a breaking change. Inside non-async methods, therefore, “await” continues to be just an identifier.

I don’t know if a similar thing is possible in EcmaScript. But I believe that a low-precedence yield as a substitute for a high-precedence await is problematic: you never want “yield a + yield b” to mean “yield (a + (yield b))”: the things you await – Task, Promises, Futures, whatever you call them – just don’t have operators defined on them, and it would be silly to parse them as if they might and then give errors (at runtime in EcmaScript, at compile time in e.g. TypeScript).

Mads


On Fri, Jun 14, 2013 at 11:07 AM, Brendan Eich <[hidden email] <mailto:[hidden email]>> wrote:

    Bruno Jouhier wrote:

        While playing with my little async/await library, I noticed
--
    Cheers,
    --MarkM
 



--
    Cheers,
    --MarkM
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Precedence of yield operator

Bruno Jouhier
In reply to this post by Mark S. Miller-2
Why not use the ! marker both for function declarations and function calls then:

  function! foo(a, b) { }
  var v = foo!(a, b);

Of, for better symmetry:

  function foo!(a, b) { }
  var v = foo!(a, b);

When you have a lot of code sitting on top of async APIs, you end up with  a high proportion of async calls. So a discreet marker is better than a heavy keyword like await.


2013/6/16 Mark S. Miller <[hidden email]>
I hadn't thought of the "urgent" implication -- interesting. I agree that this has the contrary connotations which is unfortunate.

E and AmbientTalk use "<-" which I always thought read well. In E, the "then" concept is named "when" and is also supported as a syntactic form using the "-> syntax. These work well together, as both indicate asynchrony, with the direction of the arrow indicating what is eventually being delivered to what.

In JS, "a <- b" already parses as "a < -b" so introducing a "<-" token is a non-starter. Process calculi languages like Pict (based on Pi Calculus), and languages inspired by process calculi notions like Erlang and Scala use an infix "!" for message sending, with the receiver on the left and the payload on the right. This started with Tony Hoare's CSP (Communicating Sequential Processes) and was picked up by Occam, where it was synchronous. Technically it is synchronous in the Pi Calculus too. But in Pict, Erlang, and Scala it is asynchronous. (Pict is based on the asynchronous subset of the Pi Calculus.)

More importantly for our audience, for JS (and similarly for Scala), there's also a nice mnemonic rule: Wherever you can write an infix "." you can write an infix "!" instead, changing the meaning of the construct from synchronous to asynchronous. The "!" symbol has a "." at the bottom of it, so you can think of it as "an enhanced dot" or even "a dot with a trail" if you'd like.

In any case, once the eye gets used to it the need for these mnemonics rapidly drops away. Having lived with both "<-" and "!", I've come to prefer the "!". I'm not really sure why.




On Sat, Jun 15, 2013 at 7:23 PM, Rick Waldron <[hidden email]> wrote:


On Saturday, June 15, 2013, Mark S. Miller wrote:
If we do provide such special syntax, then I suggest (a variant on some else's suggestion -- I forget who) that "yield" is to "function* as "await" is to "function!", amplifying the association of "!" with asynchrony. Rather than say "async function" or whatever, we'd just say "function!". Since "function!" would be new in ES7, there's no reason to reserve anything in ES6 to prepare for this.

Mark, is there a particular rationale for the reuse of "!" as the eventual send operator and here for similar semantics? I recall this also appeared in you Distributed Electronic Rights paper. Putting its strong existing meaning aside (negation), when I see "!" I think of "urgent" things—quite the opposite of the behavior described in the paper and above.

Rick


 




On Sat, Jun 15, 2013 at 2:40 AM, Bruno Jouhier <[hidden email]> wrote:
If this is on the agenda for ES7 maybe ES6 should at least reserve "await" as a keyword in function* scopes.


2013/6/15 François REMY <[hidden email]>
I'm maybe biased, but I would love to consider "yield" as a function. Indeed, it calls another code, which can return you a value. That looks very similar to a function call to me. If we do this, the predecence becomes intuitive again:

   var x = yield(a) + yield(b);
   yield(a+b);

I think there was a proposal to allow parenthesis-free function call at some point at the root of a statement. When it lands, you'll be able to do things like

   yield a+b;

as a normal statement again. In the mean time we can just use parentheses, that's not a huge issue and it helps clarity.



But maybe this is too late to change ES6, it's just an idea I had while reading this thread, not a strong call for change.






-----Message d'origine----- From: Brendan Eich
Sent: Saturday, June 15, 2013 6:17 AM
To: Dean Tribble
Cc: Bruno Jouhier ; [hidden email]
Subject: Re: Precedence of yield operator


This is all on the agenda for ES7. It cleanly missed ES6 in May 2011(!).

https://mail.mozilla.org/pipermail/es-discuss/2011-May/014748.html

/be

Dean Tribble wrote:
This is a familiar discussion from C#. I forwarded it to the mediator of that convresation and got a nice summary, pasted here:

---------- Forwarded message ----------
From: *Mads Torgersen* <[hidden email] <mailto:Mads.Torgersen@microsoft.com>>
Date: Fri, Jun 14, 2013 at 2:11 PM
Subject: RE: Precedence of yield operator
To: Dean Tribble <[hidden email] <mailto:[hidden email]>>


I’m not on the mailing list. Feel free to forward to it.

In C# we have separate keywords too, and indeed the precedence differs as described below. For “yield return” (our yield) the lower precendence falls out naturally since it engenders a statement, not an expression.

“await” is not a reserved keyword in C# either, but we managed to wedge it in all the same. Just adding await as an operator would lead to all kinds of ambiguity; e.g. “await (x)” could be a function call or an await expression, and the statement “await x;” could be a variable declaration or an await statement.

However, in C# “await” is only allowed inside methods marked “async”, and since there weren’t any of those around before the feature was introduced, it is not a breaking change. Inside non-async methods, therefore, “await” continues to be just an identifier.

I don’t know if a similar thing is possible in EcmaScript. But I believe that a low-precedence yield as a substitute for a high-precedence await is problematic: you never want “yield a + yield b” to mean “yield (a + (yield b))”: the things you await – Task, Promises, Futures, whatever you call them – just don’t have operators defined on them, and it would be silly to parse them as if they might and then give errors (at runtime in EcmaScript, at compile time in e.g. TypeScript).

Mads


On Fri, Jun 14, 2013 at 11:07 AM, Brendan Eich <[hidden email] <mailto:[hidden email]>> wrote:

    Bruno Jouhier wrote:

        While playing with my little async/await library, I noticed
--
    Cheers,
    --MarkM
 



--
    Cheers,
    --MarkM


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Precedence of yield operator

Mark S. Miller-2
Hi Bruno, yes the idea is to use the infix ! for async calls, but not in quite the way you mean. Have you seen <http://wiki.ecmascript.org/doku.php?id=strawman:concurrency> and <http://research.google.com/pubs/pub40673.html> ?

The basic idea is that without syntactic support, today in Q to send an asynchronous message, you'd say

    Q(p).send('foo', a,b)

In what has been codified of DOM promises, you'd say

    Promises.accept(p).then(o => o.foo(a,b))

which wouldn't even work distributed, since there is no local o on which to do a local ".". Both of these are so much heavier than 

    p.foo(a,b)

as to make asynchronous and distributed programming remain second class compared to local synchronous programming. So the full proposal is that

    p ! foo(a,b)

would mean to eventually send the message on the right to the receiver designated on the left. Likewise for

    p ! (a,b) // asynchronous function call
    p ! foo // asynchronous get
    p ! foo = x // asynchronous put
    delete p ! foo // asynchronous delete

and the computed forms of all these

    p ! [name] (a,b)
    p ! [name]
    p ! [name] = x
    delete p [name]

Over a RESTful transport <http://waterken.sourceforge.net/web_send/>, these would turn into POST, GET, PUT, and DELETE. Fortunately or unfortunately, because of CORS and UMP (something they agreed on), I expect RESTful PUT and DELETE to wither away and die in browser-to-server traffic. Our recent electronic rights paper uses only POST and GET, even though it uses only server-to-server traffic. If it can't practically be used browser-to-server, I expect it won't be used much server-to-server. Nevertheless, we should keep these forms of "!" in the language.




On Sun, Jun 16, 2013 at 2:26 AM, Bruno Jouhier <[hidden email]> wrote:
Why not use the ! marker both for function declarations and function calls then:

  function! foo(a, b) { }
  var v = foo!(a, b);

Of, for better symmetry:

  function foo!(a, b) { }
  var v = foo!(a, b);

When you have a lot of code sitting on top of async APIs, you end up with  a high proportion of async calls. So a discreet marker is better than a heavy keyword like await.


2013/6/16 Mark S. Miller <[hidden email]>

I hadn't thought of the "urgent" implication -- interesting. I agree that this has the contrary connotations which is unfortunate.

E and AmbientTalk use "<-" which I always thought read well. In E, the "then" concept is named "when" and is also supported as a syntactic form using the "-> syntax. These work well together, as both indicate asynchrony, with the direction of the arrow indicating what is eventually being delivered to what.

In JS, "a <- b" already parses as "a < -b" so introducing a "<-" token is a non-starter. Process calculi languages like Pict (based on Pi Calculus), and languages inspired by process calculi notions like Erlang and Scala use an infix "!" for message sending, with the receiver on the left and the payload on the right. This started with Tony Hoare's CSP (Communicating Sequential Processes) and was picked up by Occam, where it was synchronous. Technically it is synchronous in the Pi Calculus too. But in Pict, Erlang, and Scala it is asynchronous. (Pict is based on the asynchronous subset of the Pi Calculus.)

More importantly for our audience, for JS (and similarly for Scala), there's also a nice mnemonic rule: Wherever you can write an infix "." you can write an infix "!" instead, changing the meaning of the construct from synchronous to asynchronous. The "!" symbol has a "." at the bottom of it, so you can think of it as "an enhanced dot" or even "a dot with a trail" if you'd like.

In any case, once the eye gets used to it the need for these mnemonics rapidly drops away. Having lived with both "<-" and "!", I've come to prefer the "!". I'm not really sure why.




On Sat, Jun 15, 2013 at 7:23 PM, Rick Waldron <[hidden email]> wrote:


On Saturday, June 15, 2013, Mark S. Miller wrote:
If we do provide such special syntax, then I suggest (a variant on some else's suggestion -- I forget who) that "yield" is to "function* as "await" is to "function!", amplifying the association of "!" with asynchrony. Rather than say "async function" or whatever, we'd just say "function!". Since "function!" would be new in ES7, there's no reason to reserve anything in ES6 to prepare for this.

Mark, is there a particular rationale for the reuse of "!" as the eventual send operator and here for similar semantics? I recall this also appeared in you Distributed Electronic Rights paper. Putting its strong existing meaning aside (negation), when I see "!" I think of "urgent" things—quite the opposite of the behavior described in the paper and above.

Rick


 




On Sat, Jun 15, 2013 at 2:40 AM, Bruno Jouhier <[hidden email]> wrote:
If this is on the agenda for ES7 maybe ES6 should at least reserve "await" as a keyword in function* scopes.


2013/6/15 François REMY <[hidden email]>
I'm maybe biased, but I would love to consider "yield" as a function. Indeed, it calls another code, which can return you a value. That looks very similar to a function call to me. If we do this, the predecence becomes intuitive again:

   var x = yield(a) + yield(b);
   yield(a+b);

I think there was a proposal to allow parenthesis-free function call at some point at the root of a statement. When it lands, you'll be able to do things like

   yield a+b;

as a normal statement again. In the mean time we can just use parentheses, that's not a huge issue and it helps clarity.



But maybe this is too late to change ES6, it's just an idea I had while reading this thread, not a strong call for change.






-----Message d'origine----- From: Brendan Eich
Sent: Saturday, June 15, 2013 6:17 AM
To: Dean Tribble
Cc: Bruno Jouhier ; [hidden email]
Subject: Re: Precedence of yield operator


This is all on the agenda for ES7. It cleanly missed ES6 in May 2011(!).

https://mail.mozilla.org/pipermail/es-discuss/2011-May/014748.html

/be

Dean Tribble wrote:
This is a familiar discussion from C#. I forwarded it to the mediator of that convresation and got a nice summary, pasted here:

---------- Forwarded message ----------
From: *Mads Torgersen* <[hidden email] <mailto:Mads.Torgersen@microsoft.com>>
Date: Fri, Jun 14, 2013 at 2:11 PM
Subject: RE: Precedence of yield operator
To: Dean Tribble <[hidden email] <mailto:[hidden email]>>


I’m not on the mailing list. Feel free to forward to it.

In C# we have separate keywords too, and indeed the precedence differs as described below. For “yield return” (our yield) the lower precendence falls out naturally since it engenders a statement, not an expression.

“await” is not a reserved keyword in C# either, but we managed to wedge it in all the same. Just adding await as an operator would lead to all kinds of ambiguity; e.g. “await (x)” could be a function call or an await expression, and the statement “await x;” could be a variable declaration or an await statement.

However, in C# “await” is only allowed inside methods marked “async”, and since there weren’t any of those around before the feature was introduced, it is not a breaking change. Inside non-async methods, therefore, “await” continues to be just an identifier.

I don’t know if a similar thing is possible in EcmaScript. But I believe that a low-precedence yield as a substitute for a high-precedence await is problematic: you never want “yield a + yield b” to mean “yield (a + (yield b))”: the things you await – Task, Promises, Futures, whatever you call them – just don’t have operators defined on them, and it would be silly to parse them as if they might and then give errors (at runtime in EcmaScript, at compile time in e.g. TypeScript).

Mads


On Fri, Jun 14, 2013 at 11:07 AM, Brendan Eich <[hidden email] <mailto:[hidden email]>> wrote:

    Bruno Jouhier wrote:

        While playing with my little async/await library, I noticed
--
    Cheers,
    --MarkM
 



--
    Cheers,
    --MarkM




--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Precedence of yield operator

Mark S. Miller-2



On Sun, Jun 16, 2013 at 7:25 AM, Mark S. Miller <[hidden email]> wrote:
Hi Bruno, yes the idea is to use the infix ! for async calls, but not in quite the way you mean. Have you seen <http://wiki.ecmascript.org/doku.php?id=strawman:concurrency> and <http://research.google.com/pubs/pub40673.html> ?

The basic idea is that without syntactic support, today in Q to send an asynchronous message, you'd say

    Q(p).send('foo', a,b)

In what has been codified of DOM promises, you'd say

    Promises.accept(p).then(o => o.foo(a,b))

which wouldn't even work distributed, since there is no local o on which to do a local ".". Both of these are so much heavier than 

    p.foo(a,b)

as to make asynchronous and distributed programming remain second class compared to local synchronous programming. So the full proposal is that

    p ! foo(a,b)

would mean to eventually send the message on the right to the receiver designated on the left. Likewise for

    p ! (a,b) // asynchronous function call
    p ! foo // asynchronous get
    p ! foo = x // asynchronous put
    delete p ! foo // asynchronous delete

and the computed forms of all these

    p ! [name] (a,b)
    p ! [name]
    p ! [name] = x
    delete p [name]

Should be

    delete p ! [name]


 

Over a RESTful transport <http://waterken.sourceforge.net/web_send/>, these would turn into POST, GET, PUT, and DELETE. Fortunately or unfortunately, because of CORS and UMP (something they agreed on), I expect RESTful PUT and DELETE to wither away and die in browser-to-server traffic. Our recent electronic rights paper uses only POST and GET, even though it uses only server-to-server traffic. If it can't practically be used browser-to-server, I expect it won't be used much server-to-server. Nevertheless, we should keep these forms of "!" in the language.




On Sun, Jun 16, 2013 at 2:26 AM, Bruno Jouhier <[hidden email]> wrote:
Why not use the ! marker both for function declarations and function calls then:

  function! foo(a, b) { }
  var v = foo!(a, b);

Of, for better symmetry:

  function foo!(a, b) { }
  var v = foo!(a, b);

When you have a lot of code sitting on top of async APIs, you end up with  a high proportion of async calls. So a discreet marker is better than a heavy keyword like await.


2013/6/16 Mark S. Miller <[hidden email]>

I hadn't thought of the "urgent" implication -- interesting. I agree that this has the contrary connotations which is unfortunate.

E and AmbientTalk use "<-" which I always thought read well. In E, the "then" concept is named "when" and is also supported as a syntactic form using the "-> syntax. These work well together, as both indicate asynchrony, with the direction of the arrow indicating what is eventually being delivered to what.

In JS, "a <- b" already parses as "a < -b" so introducing a "<-" token is a non-starter. Process calculi languages like Pict (based on Pi Calculus), and languages inspired by process calculi notions like Erlang and Scala use an infix "!" for message sending, with the receiver on the left and the payload on the right. This started with Tony Hoare's CSP (Communicating Sequential Processes) and was picked up by Occam, where it was synchronous. Technically it is synchronous in the Pi Calculus too. But in Pict, Erlang, and Scala it is asynchronous. (Pict is based on the asynchronous subset of the Pi Calculus.)

More importantly for our audience, for JS (and similarly for Scala), there's also a nice mnemonic rule: Wherever you can write an infix "." you can write an infix "!" instead, changing the meaning of the construct from synchronous to asynchronous. The "!" symbol has a "." at the bottom of it, so you can think of it as "an enhanced dot" or even "a dot with a trail" if you'd like.

In any case, once the eye gets used to it the need for these mnemonics rapidly drops away. Having lived with both "<-" and "!", I've come to prefer the "!". I'm not really sure why.




On Sat, Jun 15, 2013 at 7:23 PM, Rick Waldron <[hidden email]> wrote:


On Saturday, June 15, 2013, Mark S. Miller wrote:
If we do provide such special syntax, then I suggest (a variant on some else's suggestion -- I forget who) that "yield" is to "function* as "await" is to "function!", amplifying the association of "!" with asynchrony. Rather than say "async function" or whatever, we'd just say "function!". Since "function!" would be new in ES7, there's no reason to reserve anything in ES6 to prepare for this.

Mark, is there a particular rationale for the reuse of "!" as the eventual send operator and here for similar semantics? I recall this also appeared in you Distributed Electronic Rights paper. Putting its strong existing meaning aside (negation), when I see "!" I think of "urgent" things—quite the opposite of the behavior described in the paper and above.

Rick


 




On Sat, Jun 15, 2013 at 2:40 AM, Bruno Jouhier <[hidden email]> wrote:
If this is on the agenda for ES7 maybe ES6 should at least reserve "await" as a keyword in function* scopes.


2013/6/15 François REMY <[hidden email]>
I'm maybe biased, but I would love to consider "yield" as a function. Indeed, it calls another code, which can return you a value. That looks very similar to a function call to me. If we do this, the predecence becomes intuitive again:

   var x = yield(a) + yield(b);
   yield(a+b);

I think there was a proposal to allow parenthesis-free function call at some point at the root of a statement. When it lands, you'll be able to do things like

   yield a+b;

as a normal statement again. In the mean time we can just use parentheses, that's not a huge issue and it helps clarity.



But maybe this is too late to change ES6, it's just an idea I had while reading this thread, not a strong call for change.






-----Message d'origine----- From: Brendan Eich
Sent: Saturday, June 15, 2013 6:17 AM
To: Dean Tribble
Cc: Bruno Jouhier ; [hidden email]
Subject: Re: Precedence of yield operator


This is all on the agenda for ES7. It cleanly missed ES6 in May 2011(!).

https://mail.mozilla.org/pipermail/es-discuss/2011-May/014748.html

/be

Dean Tribble wrote:
This is a familiar discussion from C#. I forwarded it to the mediator of that convresation and got a nice summary, pasted here:

---------- Forwarded message ----------
From: *Mads Torgersen* <[hidden email] <mailto:Mads.Torgersen@microsoft.com>>
Date: Fri, Jun 14, 2013 at 2:11 PM
Subject: RE: Precedence of yield operator
To: Dean Tribble <[hidden email] <mailto:[hidden email]>>


I’m not on the mailing list. Feel free to forward to it.

In C# we have separate keywords too, and indeed the precedence differs as described below. For “yield return” (our yield) the lower precendence falls out naturally since it engenders a statement, not an expression.

“await” is not a reserved keyword in C# either, but we managed to wedge it in all the same. Just adding await as an operator would lead to all kinds of ambiguity; e.g. “await (x)” could be a function call or an await expression, and the statement “await x;” could be a variable declaration or an await statement.

However, in C# “await” is only allowed inside methods marked “async”, and since there weren’t any of those around before the feature was introduced, it is not a breaking change. Inside non-async methods, therefore, “await” continues to be just an identifier.

I don’t know if a similar thing is possible in EcmaScript. But I believe that a low-precedence yield as a substitute for a high-precedence await is problematic: you never want “yield a + yield b” to mean “yield (a + (yield b))”: the things you await – Task, Promises, Futures, whatever you call them – just don’t have operators defined on them, and it would be silly to parse them as if they might and then give errors (at runtime in EcmaScript, at compile time in e.g. TypeScript).

Mads


On Fri, Jun 14, 2013 at 11:07 AM, Brendan Eich <[hidden email] <mailto:[hidden email]>> wrote:

    Bruno Jouhier wrote:

        While playing with my little async/await library, I noticed
--
    Cheers,
    --MarkM
 



--
    Cheers,
    --MarkM




--
    Cheers,
    --MarkM



--
    Cheers,
    --MarkM

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