Skip to content
This repository has been archived by the owner on Jan 28, 2023. It is now read-only.

Let’s forbid the mix of nullish-coalescing and comparison operators #48

Closed
claudepache opened this issue Jul 26, 2019 · 14 comments
Closed

Comments

@claudepache
Copy link

Currently, mixing nullish coalescing and logical operators is forbidden:

  • a ?? b && c — syntax error

If we do want such a behaviour, I strongly think that it should be extended that to relational operators:

  • a ?? b == c — syntax error.

My reasoning is the following:

Per #26 (comment), there are the following popular choices of precedence levels for ??:

  • just below || (C#, PHP, etc.) — it is the most reasonable choice if we want something very near to ||;
  • just above relational operators (Swift, Kotlin) — it is what I find in practice more useful.

Forbidding the mix of anything between those two levels of precedence has the two following concrete advantages:

  • That will avoid bugs if someone used to the precedence of Swift, resp. C#, incorrectly translate their knowledge to JavaScript. Since a ?? b == c have differing semantics in those two languages, forcing them to use parentheses in order to precise what they meant is the only way to disambiguate.

  • That will leave us the opportunity to pick the useful (Swift/Kotlin) precedence level, in some future.

@ljharb
Copy link
Member

ljharb commented Jul 26, 2019

There is lots of confusion in JS around && and || precedence; I’ve not seen this be a problem with equality comparisons.

@Mouvedia
Copy link

mixing nullish coalescing and logical operators is forbidden

Could you link to the rationale behind this decision ?

@claudepache
Copy link
Author

@ljharb This issue is not about the relative precedence between && and ||, or between || and ==, but between ?? and those operators. Which is a different matter (as ?? is not a logical operator).

@jridgewell
Copy link
Member

I’ve not seen this be a problem with equality comparisons.

Same, we've yet to have a bug with logical operators and equality.

Which is a different matter (as ?? is not a logical operator).

How is it not a logical operator?

@claudepache
Copy link
Author

How is it not a logical operator?

Nullish-coalescing is about providing a default value. Logical operators is about boolean logic.

@ljharb
Copy link
Member

ljharb commented Jul 26, 2019

No, && and || in JS are not boolean operators, they are value selection operators, exactly as ?? is. If they were boolean operators they’d produce a boolean.

@claudepache
Copy link
Author

If they were boolean operators they’d produce a boolean.

I carefully didn’t said “operators on booleans”, but “boolean logic”. The two values of that logic correspond to the notions of “truthy” and “falsy”.


But it doesn’t matter how we name it. The fact is, that ?? (and|| when used as an ersatz of ??) have typically different use cases than && and || (when not used as an ersatz of ??). (As a consequence, some languages have found it useful to give to the null-coalescing operator a markedly different precedence level than to the or-operator.)

@claudepache
Copy link
Author

Hi,

I’m thinking more and more strongly that we should ban the mix of nullish coalescing operator (??) and comparison operators (especially == and by extension <, etc.) at the same level, due to some recent observations:

@ljharb
Copy link
Member

ljharb commented Sep 20, 2019

How is that different than || or && when paired with == etc?

@claudepache
Copy link
Author

How is that different than || or && when paired with == etc?

The difference is in usage. || or && are usually used for logic (if (a && b)), or control flow (do_this() && do_that()), and the result is usually not intended to be compared with something else using a comparison operator. On the other hand, ?? (and || when used as a poor-man’s-??) is usually used for providing default values, including defaults for values that are intended to be compared using == or ===.

@ljharb
Copy link
Member

ljharb commented Sep 20, 2019

|| is exceedingly often used for value selection - for defaults - so i don’t see it as any different.

@jridgewell
Copy link
Member

  • A colleague of mine has the tendency to write (in PHP) $foo['bar']??'' === '' instead of ($foo['bar']??'') === ''.

I think this example is flawed. PHP's ?? is used for isset (something like our typeof operator) that prevents the $foo['bar'] access from throwing if bar isn't a property of $foo. But we don't that issue, and the canonical way would be foo.bar .

|| is exceedingly often used for value selection - for defaults - so i don’t see it as any different.

I disagree, I think it's pretty common to have nodeType === 3 || nodeType === 1 in tests, where the comparison operators are meant group inside the ||.

@ljharb
Copy link
Member

ljharb commented Sep 21, 2019

Sure, that’s true - but i mean, i think the exceedingly rare pattern of a TOKEN b === c will be just as common for || as for ??, warranting no additional handling.

@ljharb
Copy link
Member

ljharb commented Jan 28, 2023

Closing, since this proposal is at stage 4.

@ljharb ljharb closed this as completed Jan 28, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants