Proposal: anaphoric if and while syntax

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

Proposal: anaphoric if and while syntax

Danielle McLean
In current ECMAScript, it is legal to place a variable declaration inside the
initialiser of a `for` loop, as well as to declare the variable used by a
`for...in` or `for...of` loop within the declaring expression:

    for (let i = 0; i < 5; ++i) console.log(i);
    for (let item of collection) process(item);

When this syntax is used with `let` or `const`, the resulting variable is
scoped to the loop and is not visible to the rest of the surrounding block.

I propose that this syntax be extended, making it legal to place a variable
declaration within the condition of an `if` or `while` statement. Any truthy
value will cause the `if` block to run or `while` loop to repeat, as usual -
the advantage is that the particular truthy value is bound to a variable and
can be used inside the conditional block. For example, here is the situation
that prompted my writing this proposal:

    if (const oldValue = _.get(object, 'some.long.path')) {
      object.some.long.path = transform(oldValue);
    }

As with the existing behaviour of declarations inside `for`, variables declared
using `let` or `const` would be scoped to the individual `if` or `while`
statement, rather than the containing block. In other words, the above syntax
would be equivalent to the following currently-valid form I ended up writing:

    {
      const oldValue = _.get(object, 'some.long.path');
      if (oldValue) object.some.long.path = transform(oldValue);
    }

Another use case which C aficianados might recognise:

    while (const c = getchar()) {
        process(c);
    }

This syntax is already legal in C++, although not in C - in general this
support is known as "anaphoric if", as it allows the body of the statement to
refer back to the condition value. It's especially helpful in languages with
truthiness, which ECMAScript has, as it allows access to the *specific* truthy
value without further finagling.

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

Re: Proposal: anaphoric if and while syntax

Dan Peddle
An alternative to the block which you ended up with is to extract that logic to a function, which provides something which can be tested too. Possibly overkill for oneliners like this though.

However, writing a lot of code like this myself (get a value, if it's truthy do something, else do other), that's a nice idea for an extension that doesn't add extra variable bindings to the containing scope. 

On Tue, Sep 13, 2016 at 2:32 AM, Danielle McLean <[hidden email]> wrote:
In current ECMAScript, it is legal to place a variable declaration inside the
initialiser of a `for` loop, as well as to declare the variable used by a
`for...in` or `for...of` loop within the declaring expression:

    for (let i = 0; i < 5; ++i) console.log(i);
    for (let item of collection) process(item);

When this syntax is used with `let` or `const`, the resulting variable is
scoped to the loop and is not visible to the rest of the surrounding block.

I propose that this syntax be extended, making it legal to place a variable
declaration within the condition of an `if` or `while` statement. Any truthy
value will cause the `if` block to run or `while` loop to repeat, as usual -
the advantage is that the particular truthy value is bound to a variable and
can be used inside the conditional block. For example, here is the situation
that prompted my writing this proposal:

    if (const oldValue = _.get(object, 'some.long.path')) {
      object.some.long.path = transform(oldValue);
    }

As with the existing behaviour of declarations inside `for`, variables declared
using `let` or `const` would be scoped to the individual `if` or `while`
statement, rather than the containing block. In other words, the above syntax
would be equivalent to the following currently-valid form I ended up writing:

    {
      const oldValue = _.get(object, 'some.long.path');
      if (oldValue) object.some.long.path = transform(oldValue);
    }

Another use case which C aficianados might recognise:

    while (const c = getchar()) {
        process(c);
    }

This syntax is already legal in C++, although not in C - in general this
support is known as "anaphoric if", as it allows the body of the statement to
refer back to the condition value. It's especially helpful in languages with
truthiness, which ECMAScript has, as it allows access to the *specific* truthy
value without further finagling.

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



--

Dan Peddle
tel: +49 157 3918 2066

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

Re: Proposal: anaphoric if and while syntax

Viktor Kronvall
Does this really need new semantic interpretation of the syntax? Using the `Array.prototype` methods `.forEach` and `.map` already mitigates this problem as far as I can tell by having a different bound variable (argument in this case) for each call.

I agree that the behavior may be non-intuitive if you have a background coming from Java or C++ but the implications would be quite far-reaching and the backward compatibility with previous versions would be difficult to handle. Wouldn't this require a new 'use strict'-like mode?
2016年9月14日(水) 7:51 Dan Peddle <[hidden email]>:
An alternative to the block which you ended up with is to extract that logic to a function, which provides something which can be tested too. Possibly overkill for oneliners like this though.

However, writing a lot of code like this myself (get a value, if it's truthy do something, else do other), that's a nice idea for an extension that doesn't add extra variable bindings to the containing scope. 

On Tue, Sep 13, 2016 at 2:32 AM, Danielle McLean <[hidden email]> wrote:
In current ECMAScript, it is legal to place a variable declaration inside the
initialiser of a `for` loop, as well as to declare the variable used by a
`for...in` or `for...of` loop within the declaring expression:

    for (let i = 0; i < 5; ++i) console.log(i);
    for (let item of collection) process(item);

When this syntax is used with `let` or `const`, the resulting variable is
scoped to the loop and is not visible to the rest of the surrounding block.

I propose that this syntax be extended, making it legal to place a variable
declaration within the condition of an `if` or `while` statement. Any truthy
value will cause the `if` block to run or `while` loop to repeat, as usual -
the advantage is that the particular truthy value is bound to a variable and
can be used inside the conditional block. For example, here is the situation
that prompted my writing this proposal:

    if (const oldValue = _.get(object, 'some.long.path')) {
      object.some.long.path = transform(oldValue);
    }

As with the existing behaviour of declarations inside `for`, variables declared
using `let` or `const` would be scoped to the individual `if` or `while`
statement, rather than the containing block. In other words, the above syntax
would be equivalent to the following currently-valid form I ended up writing:

    {
      const oldValue = _.get(object, 'some.long.path');
      if (oldValue) object.some.long.path = transform(oldValue);
    }

Another use case which C aficianados might recognise:

    while (const c = getchar()) {
        process(c);
    }

This syntax is already legal in C++, although not in C - in general this
support is known as "anaphoric if", as it allows the body of the statement to
refer back to the condition value. It's especially helpful in languages with
truthiness, which ECMAScript has, as it allows access to the *specific* truthy
value without further finagling.

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



--

Dan Peddle
tel: +49 157 3918 2066
_______________________________________________
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: Proposal: anaphoric if and while syntax

Danielle McLean
On 14 September 2016 at 17:58:24, Viktor Kronvall
([hidden email](mailto:[hidden email])) wrote:

> Does this really need new semantic interpretation of the syntax? Using the `Array.prototype` methods `.forEach` and `.map` already mitigates this problem as far as I can tell by having a different bound variable (argument in this case) for each call.
>
> I agree that the behavior may be non-intuitive if you have a background coming from Java or C++ but the implications would be quite far-reaching and the backward compatibility with previous versions would be difficult to handle. Wouldn't this require a new 'use strict'-like mode?

No, adding anaphoric if as I have described it will require neither
new semantic interpretation of the syntax nor a new strictness
directive. Currently, it is a syntax error to write a variable
declaration within an `if` or `while` condition, so there is no valid
code which contains the proposed syntax.

Also note that under this proposal, declarations made using the `var`
keyword would still be hoisted to function scope, *not* scoped to the
body associated with the condition - i.e., there would be no semantic
difference whatsoever between the following two snippets:

    if (var stuff = some.cool(expression)) doThings(stuff);
    // equivalent to
    var stuff;
    if (stuff = some.cool(expression)) doThings(stuff);

Only declarations made with the newer `let` and `const` keywords,
which are never hoisted to function scope anyway, would be narrowly
scoped to the condition and its body.

    if (let stuff = expr) doThings(stuff);
    // equivalent to
    {
      let stuff = expr;
      if (stuff) doThings(stuff);
    }

(An aside: as the last example demonstrates, the `if` or `while`
statement body should not need braces to isolate the scope in this
way. This is consistent with the current behaviour for declarations in
loops.)
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: anaphoric if and while syntax

Jordan Harband
While I like the idea of making it simpler to restrict the scope of variables, currently a reigning best practice is to never do assignment in conditionals, since it can be an easy typo from `==` or `===`, and because it conflates assignment with expression truthiness, harming readability.

This seems like it runs afoul of the latter, certainly, and I haven't yet convinced myself whether it creates typo hazards (I'm thinking no, but wanted to bring it up just in case).

On Wed, Sep 14, 2016 at 3:14 AM, Danielle McLean <[hidden email]> wrote:
On 14 September 2016 at 17:58:24, Viktor Kronvall
([hidden email](mailto:[hidden email])) wrote:

> Does this really need new semantic interpretation of the syntax? Using the `Array.prototype` methods `.forEach` and `.map` already mitigates this problem as far as I can tell by having a different bound variable (argument in this case) for each call.
>
> I agree that the behavior may be non-intuitive if you have a background coming from Java or C++ but the implications would be quite far-reaching and the backward compatibility with previous versions would be difficult to handle. Wouldn't this require a new 'use strict'-like mode?

No, adding anaphoric if as I have described it will require neither
new semantic interpretation of the syntax nor a new strictness
directive. Currently, it is a syntax error to write a variable
declaration within an `if` or `while` condition, so there is no valid
code which contains the proposed syntax.

Also note that under this proposal, declarations made using the `var`
keyword would still be hoisted to function scope, *not* scoped to the
body associated with the condition - i.e., there would be no semantic
difference whatsoever between the following two snippets:

    if (var stuff = some.cool(expression)) doThings(stuff);
    // equivalent to
    var stuff;
    if (stuff = some.cool(expression)) doThings(stuff);

Only declarations made with the newer `let` and `const` keywords,
which are never hoisted to function scope anyway, would be narrowly
scoped to the condition and its body.

    if (let stuff = expr) doThings(stuff);
    // equivalent to
    {
      let stuff = expr;
      if (stuff) doThings(stuff);
    }

(An aside: as the last example demonstrates, the `if` or `while`
statement body should not need braces to isolate the scope in this
way. This is consistent with the current behaviour for declarations in
loops.)
_______________________________________________
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: Proposal: anaphoric if and while syntax

Caitlin Potter
Given that `let x == 10` or `let x === 10` is illegal, it doesn’t seem too bad to allow `if (let x = f(y))`, LexicalDeclaration is visually distinct from EqualityExpression because of the `let` or `const` prefix.


On Sep 14, 2016, at 6:41 PM, Jordan Harband <[hidden email]> wrote:

While I like the idea of making it simpler to restrict the scope of variables, currently a reigning best practice is to never do assignment in conditionals, since it can be an easy typo from `==` or `===`, and because it conflates assignment with expression truthiness, harming readability.

This seems like it runs afoul of the latter, certainly, and I haven't yet convinced myself whether it creates typo hazards (I'm thinking no, but wanted to bring it up just in case).

Given that `let x == 10` or `let x === 10` is illegal, it doesn’t seem too bad to allow `if (let x = f(y))`, LexicalDeclaration is visually distinct from EqualityExpression because of the `let` or `const` prefix.


On Wed, Sep 14, 2016 at 3:14 AM, Danielle McLean <[hidden email]> wrote:
On 14 September 2016 at 17:58:24, Viktor Kronvall
([hidden email](mailto:[hidden email])) wrote:

> Does this really need new semantic interpretation of the syntax? Using the `Array.prototype` methods `.forEach` and `.map` already mitigates this problem as far as I can tell by having a different bound variable (argument in this case) for each call.
>
> I agree that the behavior may be non-intuitive if you have a background coming from Java or C++ but the implications would be quite far-reaching and the backward compatibility with previous versions would be difficult to handle. Wouldn't this require a new 'use strict'-like mode?

No, adding anaphoric if as I have described it will require neither
new semantic interpretation of the syntax nor a new strictness
directive. Currently, it is a syntax error to write a variable
declaration within an `if` or `while` condition, so there is no valid
code which contains the proposed syntax.

Also note that under this proposal, declarations made using the `var`
keyword would still be hoisted to function scope, *not* scoped to the
body associated with the condition - i.e., there would be no semantic
difference whatsoever between the following two snippets:

    if (var stuff = some.cool(expression)) doThings(stuff);
    // equivalent to
    var stuff;
    if (stuff = some.cool(expression)) doThings(stuff);

Only declarations made with the newer `let` and `const` keywords,
which are never hoisted to function scope anyway, would be narrowly
scoped to the condition and its body.

    if (let stuff = expr) doThings(stuff);
    // equivalent to
    {
      let stuff = expr;
      if (stuff) doThings(stuff);
    }

(An aside: as the last example demonstrates, the `if` or `while`
statement body should not need braces to isolate the scope in this
way. This is consistent with the current behaviour for declarations in
loops.)
_______________________________________________
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


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

signature.asc (859 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: anaphoric if and while syntax

Oriol _
In reply to this post by Danielle McLean
I like this proposal. Specially for `while` loops.

When I want to iterate all matches of a global regex, I always think the variable declaration at the top seems ugly

```js
let match;
while (match = regex.exec(string)) {
  // ...
}
```

This looks better:

```js
while (let match = regex.exec(string)) {
  // ...
}
```

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

Re: Proposal: anaphoric if and while syntax

Jordan Harband
For what it's worth, that specific use case would be addressed by https://github.com/tc39/String.prototype.matchAll ;-)

On Wed, Sep 14, 2016 at 4:20 PM, Oriol Bugzilla <[hidden email]> wrote:
I like this proposal. Specially for `while` loops.

When I want to iterate all matches of a global regex, I always think the variable declaration at the top seems ugly

```js
let match;
while (match = regex.exec(string)) {
  // ...
}
```

This looks better:

```js
while (let match = regex.exec(string)) {
  // ...
}
```

_______________________________________________
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: Proposal: anaphoric if and while syntax

Bergi
In reply to this post by Danielle McLean
Danielle McLean wrote:

> variables declared
> using `let` or `const` would be scoped to the individual `if` or `while`
> statement, rather than the containing block. In other words, the above syntax
> would be equivalent to the following currently-valid form I ended up writing:
>
>     {
>       const oldValue = _.get(object, 'some.long.path');
>       if (oldValue) object.some.long.path = transform(oldValue);
>     }

What about `else` blocks, would the variables be available in them as well?

- Bergi

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

Re: Proposal: anaphoric if and while syntax

Alan Johnson

What about `else if`?


On Sep 14, 2016 9:28 PM, "Bergi" <[hidden email]> wrote:
Danielle McLean wrote:

variables declared
using `let` or `const` would be scoped to the individual `if` or `while`
statement, rather than the containing block. In other words, the above syntax
would be equivalent to the following currently-valid form I ended up writing:

    {
      const oldValue = _.get(object, 'some.long.path');
      if (oldValue) object.some.long.path = transform(oldValue);
    }

What about `else` blocks, would the variables be available in them as well?

- Bergi

_______________________________________________
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: Re: Proposal: anaphoric if and while syntax

Danielle McLean
In reply to this post by Danielle McLean
"Bergi" <a.d.bergi at web.de> wrote:

> What about `else` blocks, would the variables be available in them as well?

No. If the `else` block executes, then the variable's value would be
falsy and therefore presumably not useful for further processing. Of
course, there are multiple falsy values in ES, but knowing which
specific falsy value a condition produced is far less useful than
knowing which specific truthy value a condition produced.

If you've got a use case for the variable's scope extending into the
`else` block, though, feel free to change this. ;)

"Alan Johnson" <alan at breakrs.com> wrote:

> What about `else if`?

As with a standalone `else`, the `else if` branches are only reached
if the value from the `if` branch was falsy and therefore presumably
not useful. So, again, the variable from the original `if` condition
need not be available.

It should however be possible to declare *another* variable in an
`else if`'s condition, for consistency. Like this:

```js
if (const x = expr()) {
  // use x
} else if (const x = expr2()) {
  // use x in a different way
} else {
  // couldn't get either kind of x :(
}
```
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: anaphoric if and while syntax

Mark Volkmann
In reply to this post by Alan Johnson
For what it's worth, I'm on the side of people that do not want to see assignment statements in control structures. I don't think it is necessary and it results in code that is harder to read.

On Wed, Sep 14, 2016 at 8:51 PM, Alan Johnson <[hidden email]> wrote:

What about `else if`?


On Sep 14, 2016 9:28 PM, "Bergi" <[hidden email]> wrote:
Danielle McLean wrote:

variables declared
using `let` or `const` would be scoped to the individual `if` or `while`
statement, rather than the containing block. In other words, the above syntax
would be equivalent to the following currently-valid form I ended up writing:

    {
      const oldValue = _.get(object, 'some.long.path');
      if (oldValue) object.some.long.path = transform(oldValue);
    }

What about `else` blocks, would the variables be available in them as well?

- Bergi

_______________________________________________
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




--
R. Mark Volkmann
Object Computing, Inc.

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

Re: Proposal: anaphoric if and while syntax

Andy Earnshaw-2
How so? Assignment is already possible in control structures.  I think this reads better:

```
if (let a = foo) {
```

Than:

```
let a;

//...

if (a = foo) {
```

Having the `let` or `const` inside the conditional part clarifies the intent. There's an argument for not doing assignment inside the conditional part, but it's subjective and people will write code that way regardless. I'd much rather see `let` or `const` next to code like that if it means mistakes are less likely to be made. 

On Thu, 15 Sep 2016, 15:17 Mark Volkmann, <[hidden email]> wrote:
For what it's worth, I'm on the side of people that do not want to see assignment statements in control structures. I don't think it is necessary and it results in code that is harder to read.

On Wed, Sep 14, 2016 at 8:51 PM, Alan Johnson <[hidden email]> wrote:

What about `else if`?


On Sep 14, 2016 9:28 PM, "Bergi" <[hidden email]> wrote:
Danielle McLean wrote:

variables declared
using `let` or `const` would be scoped to the individual `if` or `while`
statement, rather than the containing block. In other words, the above syntax
would be equivalent to the following currently-valid form I ended up writing:

    {
      const oldValue = _.get(object, 'some.long.path');
      if (oldValue) object.some.long.path = transform(oldValue);
    }

What about `else` blocks, would the variables be available in them as well?

- Bergi

_______________________________________________
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




--
R. Mark Volkmann
Object Computing, Inc.
_______________________________________________
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: Proposal: anaphoric if and while syntax

Kris Siegel
I really like the idea of declaring a variable directly in the conditional itself. Many other languages do it. It's certainly not a critical thing (it makes 2 lines of code into 1) but I certainly would like it to happen. Considering it only moves the declaration I'm not convinced it makes code harder to read; in fact since you are explicitly saying it's part of the conditional you're declaring it in I feel like that makes it more clear as there is no longer a risk of someone re-using that variable outside of, say, the while loop it's declared in (which is what can happen today).

I know we don't have voting but this sure has my vote. I'd love to see it championed at an upcoming meeting.

On Thu, Sep 15, 2016 at 9:22 AM, Andy Earnshaw <[hidden email]> wrote:
How so? Assignment is already possible in control structures.  I think this reads better:

```
if (let a = foo) {
```

Than:

```
let a;

//...

if (a = foo) {
```

Having the `let` or `const` inside the conditional part clarifies the intent. There's an argument for not doing assignment inside the conditional part, but it's subjective and people will write code that way regardless. I'd much rather see `let` or `const` next to code like that if it means mistakes are less likely to be made. 


On Thu, 15 Sep 2016, 15:17 Mark Volkmann, <[hidden email]> wrote:
For what it's worth, I'm on the side of people that do not want to see assignment statements in control structures. I don't think it is necessary and it results in code that is harder to read.

On Wed, Sep 14, 2016 at 8:51 PM, Alan Johnson <[hidden email]> wrote:

What about `else if`?


On Sep 14, 2016 9:28 PM, "Bergi" <[hidden email]> wrote:
Danielle McLean wrote:

variables declared
using `let` or `const` would be scoped to the individual `if` or `while`
statement, rather than the containing block. In other words, the above syntax
would be equivalent to the following currently-valid form I ended up writing:

    {
      const oldValue = _.get(object, 'some.long.path');
      if (oldValue) object.some.long.path = transform(oldValue);
    }

What about `else` blocks, would the variables be available in them as well?

- Bergi

_______________________________________________
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




--
R. Mark Volkmann
Object Computing, Inc.
_______________________________________________
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



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

Re: Proposal: anaphoric if and while syntax

Andy Earnshaw-2
In reply to this post by Danielle McLean
The main barrier that I can see is that this requires new semantics.  At the moment, variable declarations don't have any kind of usable result.  If you consider

    let a = eval('let b = 1');
    console.log(a);
    //-> undefined

This sounds like an easy thing to solve, but how about this:

    if (let a = foo(), b = bar()) {
    }

Does the block execute if `a` and `b` are both truthy, or just `b`?  My gut instinct says "if bar() is truthy", but it still seems awkward.  Any option might be confusing depending on your level of experience.   What about this:

    if (let { a, b } = foo) {
    }

Does the block execute if `a` and `b` are both truthy, just `b`, or if `foo` is truthy?  I'd lean towards `foo` in this case, but I think it looks pretty bad and I'd hate to see it in code.  It might make more sense to throw for destructuring or if there's more than one assignment.

On Tue, 13 Sep 2016 at 01:32 Danielle McLean <[hidden email]> wrote:
In current ECMAScript, it is legal to place a variable declaration inside the
initialiser of a `for` loop, as well as to declare the variable used by a
`for...in` or `for...of` loop within the declaring expression:

    for (let i = 0; i < 5; ++i) console.log(i);
    for (let item of collection) process(item);

When this syntax is used with `let` or `const`, the resulting variable is
scoped to the loop and is not visible to the rest of the surrounding block.

I propose that this syntax be extended, making it legal to place a variable
declaration within the condition of an `if` or `while` statement. Any truthy
value will cause the `if` block to run or `while` loop to repeat, as usual -
the advantage is that the particular truthy value is bound to a variable and
can be used inside the conditional block. For example, here is the situation
that prompted my writing this proposal:

    if (const oldValue = _.get(object, 'some.long.path')) {
      object.some.long.path = transform(oldValue);
    }

As with the existing behaviour of declarations inside `for`, variables declared
using `let` or `const` would be scoped to the individual `if` or `while`
statement, rather than the containing block. In other words, the above syntax
would be equivalent to the following currently-valid form I ended up writing:

    {
      const oldValue = _.get(object, 'some.long.path');
      if (oldValue) object.some.long.path = transform(oldValue);
    }

Another use case which C aficianados might recognise:

    while (const c = getchar()) {
        process(c);
    }

This syntax is already legal in C++, although not in C - in general this
support is known as "anaphoric if", as it allows the body of the statement to
refer back to the condition value. It's especially helpful in languages with
truthiness, which ECMAScript has, as it allows access to the *specific* truthy
value without further finagling.

Thoughts?
_______________________________________________
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: Proposal: anaphoric if and while syntax

Kris Siegel
I agree but at the same time those examples simply look like bad coding practices to me and we can't completely hide from those. Since it's new semantics we shouldn't have to worry about it breaking something existing and it would be really easy to do a transpile back into ES5 or ES6 should people want to use it ahead of time.

Just my 2 cents. You certainly have valid points. The only awkward thing, in my opinion, is if we're using let and const we're going to have to allow var as well (it would be odd that, in a single place, you can use let and const but not var). Not sure how var should be really handled here; probably allow it but make it a bad practice to use var in this type of declaration. In my opinion anyway.

On Thu, Sep 15, 2016 at 11:15 AM, Andy Earnshaw <[hidden email]> wrote:
The main barrier that I can see is that this requires new semantics.  At the moment, variable declarations don't have any kind of usable result.  If you consider

    let a = eval('let b = 1');
    console.log(a);
    //-> undefined

This sounds like an easy thing to solve, but how about this:

    if (let a = foo(), b = bar()) {
    }

Does the block execute if `a` and `b` are both truthy, or just `b`?  My gut instinct says "if bar() is truthy", but it still seems awkward.  Any option might be confusing depending on your level of experience.   What about this:

    if (let { a, b } = foo) {
    }

Does the block execute if `a` and `b` are both truthy, just `b`, or if `foo` is truthy?  I'd lean towards `foo` in this case, but I think it looks pretty bad and I'd hate to see it in code.  It might make more sense to throw for destructuring or if there's more than one assignment.

On Tue, 13 Sep 2016 at 01:32 Danielle McLean <[hidden email]> wrote:
In current ECMAScript, it is legal to place a variable declaration inside the
initialiser of a `for` loop, as well as to declare the variable used by a
`for...in` or `for...of` loop within the declaring expression:

    for (let i = 0; i < 5; ++i) console.log(i);
    for (let item of collection) process(item);

When this syntax is used with `let` or `const`, the resulting variable is
scoped to the loop and is not visible to the rest of the surrounding block.

I propose that this syntax be extended, making it legal to place a variable
declaration within the condition of an `if` or `while` statement. Any truthy
value will cause the `if` block to run or `while` loop to repeat, as usual -
the advantage is that the particular truthy value is bound to a variable and
can be used inside the conditional block. For example, here is the situation
that prompted my writing this proposal:

    if (const oldValue = _.get(object, 'some.long.path')) {
      object.some.long.path = transform(oldValue);
    }

As with the existing behaviour of declarations inside `for`, variables declared
using `let` or `const` would be scoped to the individual `if` or `while`
statement, rather than the containing block. In other words, the above syntax
would be equivalent to the following currently-valid form I ended up writing:

    {
      const oldValue = _.get(object, 'some.long.path');
      if (oldValue) object.some.long.path = transform(oldValue);
    }

Another use case which C aficianados might recognise:

    while (const c = getchar()) {
        process(c);
    }

This syntax is already legal in C++, although not in C - in general this
support is known as "anaphoric if", as it allows the body of the statement to
refer back to the condition value. It's especially helpful in languages with
truthiness, which ECMAScript has, as it allows access to the *specific* truthy
value without further finagling.

Thoughts?
_______________________________________________
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



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

Re: Proposal: anaphoric if and while syntax

Steve Fink
In reply to this post by Danielle McLean
On 09/12/2016 05:32 PM, Danielle McLean wrote:

> In current ECMAScript, it is legal to place a variable declaration inside the
> initialiser of a `for` loop, as well as to declare the variable used by a
> `for...in` or `for...of` loop within the declaring expression:
>
>      for (let i = 0; i < 5; ++i) console.log(i);
>      for (let item of collection) process(item);
>
> When this syntax is used with `let` or `const`, the resulting variable is
> scoped to the loop and is not visible to the rest of the surrounding block.
>
> I propose that this syntax be extended, making it legal to place a variable
> declaration within the condition of an `if` or `while` statement. Any truthy
> value will cause the `if` block to run or `while` loop to repeat, as usual -
> the advantage is that the particular truthy value is bound to a variable and
> can be used inside the conditional block.

My initial reaction was positive, but now I don't think it works.

First, other places in the grammar do not restrict let/const to a single
variable. Should

   if (let a=0, b=1, c=0) { ... }

execute the if block or not? The obvious solution is to require a single
variable, which means the grammar for these let/consts is different from
others. What about

   x = { a: 1 };
   if (let {a} = x) { ... }

Second, that previous example makes it unclear to me at first glance
what the intended semantics *should* be. I could imagine this printing
either 1 or 2:

   h = { foo: 0};
   if (let {bar=1} = h) {
     print(1);
   } else {
     print(2);
   }

Is the conditional based on the variable's final value, or on whether or
not the destructuring found a match? I could argue for either one, so
even if there's a natural way to resolve my first problem, I think the
code looks ambiguous to the eye.

   if (let { children } = node) {
     print("interior node");
   } else {
     print("leaf node");
   }

Again, the simplest way to resolve this is to restrict it to "let/const
IDENTIFIER = expression", but it feels weird to have different rules for
this particular case. for(let...) on the other hand, does not attempt to
use the let expression as a value, so it does not encounter any of these
problems.

As a minor issue, it also feels a little awkward to special-case this
conditional expression. I can do

   if (let x = foo()) print(x)

but not

   (let x = foo()) && print(x)

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

Re: Proposal: anaphoric if and while syntax

J Decker
In reply to this post by Andy Earnshaw-2
Why not more generally - allow let/var declarations in expressions?

coming from a long and rich C background, I have no issues with the existing mechanisms... but for those languages that do support variable declarations in for loops; I've always wondered why not any expression?  

if( let a = ( let b = 10 ) * 3 > 10 )
... or ...

c = (let a = b*d)

granted, the scope is extremely limited in the last case...

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

Re: Proposal: anaphoric if and while syntax

Andrea Giammarchi-2
if( let a = ( let b = 10 ) * 3 > 10 )

I've honestly no idea, at first/quick read, what the hell that would produce.

Is `a` going to be just `true` ? 'cause if not, this proposal violates operator precedence.

If yes ... why would anyone write that ?

On Thu, Sep 15, 2016 at 7:30 PM, J Decker <[hidden email]> wrote:
Why not more generally - allow let/var declarations in expressions?

coming from a long and rich C background, I have no issues with the existing mechanisms... but for those languages that do support variable declarations in for loops; I've always wondered why not any expression?  

if( let a = ( let b = 10 ) * 3 > 10 )
... or ...

c = (let a = b*d)

granted, the scope is extremely limited in the last case...

_______________________________________________
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: Proposal: anaphoric if and while syntax

Jeremy Martin
If yes ... why would anyone write that ?

I think it would have to be "yes" (and that's probably just a contrived example that doesn't demonstrate the usefulness).

Slightly less contrived, I could see the value in this, though. E.g.,

```
router.get('/user', (req, res, next) => {
    if (let user = req.session.user) {
        // do stuff with user here
    } else {
        res.status(401).end();
    }
});
```

I don't think it works as cleanly with `var`, but `const` and `let` has some nice precedence with for-statements.


On Thu, Sep 15, 2016 at 2:45 PM, Andrea Giammarchi <[hidden email]> wrote:
if( let a = ( let b = 10 ) * 3 > 10 )

I've honestly no idea, at first/quick read, what the hell that would produce.

Is `a` going to be just `true` ? 'cause if not, this proposal violates operator precedence.

If yes ... why would anyone write that ?

On Thu, Sep 15, 2016 at 7:30 PM, J Decker <[hidden email]> wrote:
Why not more generally - allow let/var declarations in expressions?

coming from a long and rich C background, I have no issues with the existing mechanisms... but for those languages that do support variable declarations in for loops; I've always wondered why not any expression?  

if( let a = ( let b = 10 ) * 3 > 10 )
... or ...

c = (let a = b*d)

granted, the scope is extremely limited in the last case...

_______________________________________________
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




--
Jeremy Martin
661.312.3853
@jmar777

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