# Problems of ||==, ||=== etc. and an alternative

**URL:** <https://es.discourse.group/t/problems-of-etc-and-an-alternative/2088>\
**Category:** 💡 Ideas\
**Tags:** proposal\
**Created:** [July 15, 2024, 10:05am UTC](https://es.discourse.group/t/problems-of-etc-and-an-alternative/2088 "2024-07-15T10:05:26Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![oleedd](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/oleedd/32/2148_2.png) [@oleedd](https://es.discourse.group/u/oleedd)\
**Post date:** [July 15, 2024, 10:05am UTC](https://es.discourse.group/t/problems-of-etc-and-an-alternative/2088/1 "2024-07-15T10:05:26Z")

</div>

It is a branch from this big topic: [Operators: ||==, ||===](https://es.discourse.group/t/operators/1577)  
`if (a ||=== "first-comparison" ||=== "second-comparison" ||=== "third-comparison" ) ...`  
It has problems. It probably can't work because `a ||=== "first-comparison"` should return `false` to continue and the next check will compare with `false`.  
I propose an operator for variants, for example `|` how it works in regex.  
`if (a ||=== "first-comparison" | "second-comparison" | "third-comparison") ...`  
Tell me what do you think about the problem and this proposal.

---

<div class="post-metadata">

**Author:** ![oleedd](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/oleedd/32/2148_2.png) [@oleedd](https://es.discourse.group/u/oleedd)\
**Post date:** [July 15, 2024, 10:30am UTC](https://es.discourse.group/t/problems-of-etc-and-an-alternative/2088/2 "2024-07-15T10:30:31Z")

</div>

Or two variant operators to avoid adding new `||==`, `&&===`, `||!=`, `||>` and others. For example, `&` - "and" variant, `|` - "or" variant. Then:  
`if (a === "first-comparison" | "second-comparison" | "third-comparison") ... if (a === "first-comparison" & "second-comparison" & "third-comparison") ...`

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [July 15, 2024, 2:32pm UTC](https://es.discourse.group/t/problems-of-etc-and-an-alternative/2088/3 "2024-07-15T14:32:40Z")

</div>

Those tokens are already bitwise operators.

---

<div class="post-metadata">

**Author:** ![oleedd](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/oleedd/32/2148_2.png) [@oleedd](https://es.discourse.group/u/oleedd)\
**Post date:** [July 15, 2024, 3:10pm UTC](https://es.discourse.group/t/problems-of-etc-and-an-alternative/2088/4 "2024-07-15T15:10:07Z")

</div>

Ok, never used them. Then something different.  
Maybe "-|" and "-&". Or "?|" and "?&".  
Or "#" and "\". To be single symbol.  
Or "|||" and "&&&". But too many symbols.

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [July 15, 2024, 3:47pm UTC](https://es.discourse.group/t/problems-of-etc-and-an-alternative/2088/5 "2024-07-15T15:47:44Z")

</div>

If your concern is that there's too many symbols, it seems far simpler to repeat the comparison - `x ||=== y || x ||=== z` rather than inventing a new kind of symbol?

---

<div class="post-metadata">

**Author:** ![oleedd](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/oleedd/32/2148_2.png) [@oleedd](https://es.discourse.group/u/oleedd)\
**Post date:** [July 15, 2024, 3:57pm UTC](https://es.discourse.group/t/problems-of-etc-and-an-alternative/2088/6 "2024-07-15T15:57:46Z")

</div>

But how will it work? What steps of execution? I could not build steps due to the problem described in the first post.

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [July 15, 2024, 4:10pm UTC](https://es.discourse.group/t/problems-of-etc-and-an-alternative/2088/7 "2024-07-15T16:10:45Z")

</div>

`if (a ||=== "first-comparison" || a ||=== "second-comparison" || a ||=== "third-comparison")`

or `&&` instead of `||`, if that's the semantics you want. Personally i'd indent it like this for readability:

```javascript
if (
a ||=== "first-comparison"
>> a ||=== "second-comparison"
>> a ||=== "third-comparison"
) {

```

---

<div class="post-metadata">

**Author:** ![oleedd](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/oleedd/32/2148_2.png) [@oleedd](https://es.discourse.group/u/oleedd)\
**Post date:** [July 15, 2024, 4:16pm UTC](https://es.discourse.group/t/problems-of-etc-and-an-alternative/2088/8 "2024-07-15T16:16:19Z")

</div>

As I understand, `a ||=== "first-comparison"` should return something because both `===` and `||` return. What will it return?

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [July 15, 2024, 4:32pm UTC](https://es.discourse.group/t/problems-of-etc-and-an-alternative/2088/9 "2024-07-15T16:32:14Z")

</div>

Sorry I didn't realize this sooner, but `||===` isn't a thing, so that'll be a syntax error.

There's `||`, `===`, and `||=`, the latter of which is an assignment operator.

The condition you want seems to be `a === 'first' || a === 'second' || a === 'third'`.

---

<div class="post-metadata">

**Author:** ![oleedd](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/oleedd/32/2148_2.png) [@oleedd](https://es.discourse.group/u/oleedd)\
**Post date:** [July 15, 2024, 4:43pm UTC](https://es.discourse.group/t/problems-of-etc-and-an-alternative/2088/10 "2024-07-15T16:43:47Z")

</div>

Then why the initial thread ([Operators: ||==, ||===](https://es.discourse.group/t/operators/1577)) has 37 posts if the `||=` assignment was added in 2020?  
Stop, there will not be `||=`, only 2 and 3 `=`, not 1.  
Anyway, it can be reversed: `===||`. But the question is open: what will it return? I mean when chained. I could not find a solution that is why I propose a variant operator. But it doesn't give the ability to make different checks.

---

<div class="post-metadata">

**Author:** ![lightmare](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/lightmare/32/843_2.png) [@lightmare](https://es.discourse.group/u/lightmare)\
**Post date:** [July 16, 2024, 7:48am UTC](https://es.discourse.group/t/problems-of-etc-and-an-alternative/2088/11 "2024-07-16T07:48:15Z")

</div>

> [@oleedd](#):
>
> It has problems.

Agreed.

> [@oleedd](#):
>
> It probably can't work because `a ||=== "first-comparison"` should return `false` to continue and the next check will compare with `false`.

This ain't one, though.

You're treating it like a binary operator, which is not what was proposed in the original thread. It was meant to be syntax for expressing `n`-ary operations, with `n >= 3`. The expression `(a ||== b ||== c)` is not identical to `((a ||== b) ||== c)`, author suggested the latter would be syntax error.

Consider existing ternary conditional: `(a ? b : c)`. You don't treat the `?` and `:` as stand-alone operators, or require that `a ? b` be a sub-expression of its own that returns something.

---

<div class="post-metadata">

**Author:** ![oleedd](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/oleedd/32/2148_2.png) [@oleedd](https://es.discourse.group/u/oleedd)\
**Post date:** [July 16, 2024, 8:18am UTC](https://es.discourse.group/t/problems-of-etc-and-an-alternative/2088/12 "2024-07-16T08:18:05Z")

</div>

> [@lightmare](#):
>
> This ain't one, though.

And what are?

> [@lightmare](#):
>
> syntax for expressing `n` -ary operations, with `n >= 3`

Why \>= 3? Why not \>= 2?

> [@lightmare](#):
>
> You're treating it like a binary operator, which is not what was proposed in the original thread. It was meant to be syntax for expressing `n`-ary operations, with `n >= 3`. The expression `(a ||== b ||== c)` is not identical to `((a ||== b) ||== c)`, author suggested the latter would be syntax error.

It is weird because JavaScript doesn't work so. And because both `||` and `===` return values.  
`a ? b : c` may be considered as a single operation but not chains with `||==` because the engines should remember the value of `a` and comparison result several times, not once. Engines do next steps basing on what was returned. `a` in `a ? b : c` returns boolean from itself. We don't see it but it is in the internal process. Such returns are required to let the engines know how to handle things.

---

<div class="post-metadata">

**Author:** ![lightmare](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/lightmare/32/843_2.png) [@lightmare](https://es.discourse.group/u/lightmare)\
**Post date:** [July 16, 2024, 3:35pm UTC](https://es.discourse.group/t/problems-of-etc-and-an-alternative/2088/13 "2024-07-16T15:35:21Z")

</div>

Please read the original thread thoroughly. Your argument that it cannot work is akin to saying arrow function expressions cannot work, because both `=` and `>` return values, and when I write `x => y => x + y`, the `x => y` should return something to pass to the next step. `x => y` is not a thing in the parse tree of that expression, and `=>` has nothing to do with `=` or `>`.

You're trying to solve a non-issue. All the examples involving `||==` et al can easily be rewritten into existing syntax, proving that it can work.

Ignore the similarity of `||==` to binary operators you know, and think of the comparison chain as a function call with hidden name and parentheses, and commas replaced with funny symbol soup. The only difference would be how many times operands are evaluated:

```javascript
a ||== b ||== c // a, b evaluated 1x, c evaluated 0-1x
(_a=a) == b || _a == c // same as above
ternaryEqOrEq(a, b, c) // all evaluated 1x

```

```javascript
v ||== okay ||== fine &&!= bad &&!= worse // v, okay evaluated 1x, rest 0-1x
((_v=v) == okay || _v == fine) && _v != bad && _v != worse // same as above
tetraryEqOrEqAndNeAndNe(v, okay, fine, bad, worse) // all evaluated 1x

```

BTW, this is similar to how optional chaining is transpiled into legacy JS. In `foo?.bar`, the sub-expression `foo` must be evaluated exactly once, but its value is needed 3 times: twice for checking it's not null or undefined, and then for the actual member access. Transpilers use a temporary for that: `(tmp = foo) === null || tmp === void 0 ? void 0 : tmp.bar`

* * *

Now to address your questions.

> [@oleedd](#):
>
> Why \>= 3? Why not \>= 2?

That was the original author's choice, and it kinda makes sense because for `n == 2` the operation would be identical to a simple existing comparison. Whether you define `(a ||== b)` to be a syntax error, or identical to `(a == b)` is a bikeshedding matter.

> [@oleedd](#):
>
> And what are?

For me, one issue is that the `||` or `&&` in the first symbol is irrelevant:

```javascript
// same thing:
A ||== B ||== C
A &&== B ||== C

```

I think a cleaner solution would be to only allow this n-ary comparison chain on the RHS of existing comparison operators in the grammar, so you'd have:

```javascript
A == B ||== C
// note that this is NOT two binary operations;
// it's a ternary operation with operands A, B, C

```

* * *

Another issue is that the author considers the ability to mix different logical operations in one comparison chain a desirable feature. I think it's questionable at best. Here's an example by the author:

```javascript
if( value ||=== allowed1 ||=== allowed2 &&!== forbidden )
// same as
if ((value === allowed1 || value === allowed2) && value !== forbidden)

```

Notice how in order to understand this code, you must resist the urge to apply logical operator precedence rules you know and be aware that the three pair-wise comparisons within this 4-ary chain happen in source text order (left-to-right).

Another thing that's unlike existing boolean operations, is that in mixed-logical chain, you cannot arbitrarily flip operands around "operators" without changing the outcome.

With same-logical chain, or with binary logical operators, changing `A op B` to `B op A` won't change the result (unless it depends on operand evaluation side-effects, of course). So you can easily check the forbidden value first:

```javascript
if (value !== forbidden && (value === allowed1 || value === allowed2))

```

But there's no way to rewrite the above with a single comparison chain as proposed, while maintaining the order of comparisons.

---

<div class="post-metadata">

**Author:** ![oleedd](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/oleedd/32/2148_2.png) [@oleedd](https://es.discourse.group/u/oleedd)\
**Post date:** [July 16, 2024, 4:27pm UTC](https://es.discourse.group/t/problems-of-etc-and-an-alternative/2088/14 "2024-07-16T16:27:59Z")

</div>

> [@lightmare](#):
>
> Your argument that it cannot work is akin to saying arrow function expressions cannot work, because both `=` and `>` return values, and when I write `x => y => x + y`, the `x => y` should return something to pass to the next step. `x => y` is not a thing in the parse tree of that expression, and `=>` has nothing to do with `=` or `>`.

It is too much. Maybe you will start parsing symbols into glyphs? I am sure that it can't pass all 4 stages because no logical return values for steps for the engines.

> [@lightmare](#):
>
> `=>` has nothing to do with `=` or `>`

Yes, but `||===` is combined unlike `=>`.

Another problem is that if no return values, if `a ||=== "first-comparison"` means comparing `a` with `"first-comparison"`, then `"first-comparison" ||=== "second-comparison"` means comparing `"first-comparison"` with `"second-comparison"`. The engines are not a magic wand, they need logical steps, as much as the specification.

> [@lightmare](#):
>
> Another issue is that the author considers the ability to mix different logical operations in one comparison chain a desirable feature. I think it's questionable at best.

It is just what should be. If no mixing, just create 2 variant operators what I propose to not create as much as 16 (if not more) combined operators.

> [@lightmare](#):
>
> and it kinda makes sense because for `n == 2` the operation would be identical to a simple existing comparison

I don't see any sense. Why if it is to skip repeating `a` to write it only 1 time, not 2, not 3 and so on. And I don't think that counting is a rightful thing at all. JavaScript doesn't work so.

> [@lightmare](#):
>
> I think a cleaner solution would be to only allow this n-ary comparison chain on the RHS of existing comparison operators in the grammar, so you'd have:
> 
> ```javascript
> A == B ||== C
> // note that this is NOT two binary operations;
> // it's a ternary operation with operands A, B, C
> 
> ```

It is just what I propose. Variant operators. Like ternary operations. Notice that it requires different operators, not only one. No sense in repeating `==` after. It is better to create 2 new ("or" and "and"), than 16 combined. But it doesn't allow to mix what is sad.

> [@lightmare](#):
>
> Another thing that's unlike existing boolean operations, is that in mixed-logical chain, you cannot arbitrarily flip operands around "operators" without changing the outcome.

Yes. Even in not mixed. It is when non-strict comparisons.
