-
Notifications
You must be signed in to change notification settings - Fork 92
Description
The switch expression is currently specified to be at relational precedence. I propose to change it to be at primary precedence. See HERE for the precedence chart of existing operators.
The reason for this proposed change is that the switch expression behaves more similarly to postfix unary operators (which are primary expressions) than it does to any kind of binary operator. For example, it has one operand that appear to the left. The current situation is somewhat confusing, and I believe the proposed change will remove most confusion.
Issue 1: Confusing precedence inversion
With relational precedence, it is not legal to write
x = e switch {...} + 1; // syntax error today
Because this code attempts to write an addition in which the left operand is of higher precedence. The result is simply a syntax error. Fixing this requires awkwardly parenthesizing the whole switch expression:
x = (e switch {...}) + 1; // ok
It is difficult to explain this error (and fix) to the user, as the switch is obviously the left operand of the addition.
With primary precedence, the original code is legal and has the obvious intended meaning:
x = e switch {...} + 1; // proposed OK
Issue 2: Unclear operands
With relational precedence, it is not clear which is the operand to the switch expression:
x = a + b switch {...}; // what is the switch's left operand?
x = a & b switch {...}; // what is the switch's left operand?
The answer is that the left operand is a + b
today on the first line, but b
on the second line. If you wanted the operand to be only b
in the first line, you would have to awkwardly parenthesize the entire switch expression.
With primary precedence, the switch expression's operand is b
for both lines. If you want the operand to be a + b
or a & b
, you can simply parenthesize that operand. That will feel natural to users, who may even expect the switch expression's operand to always be parenthesized as a matter of style.
Issue 3: primary vs unary
Why do I propose primary rather than unary precedence? There are pros and cons of primary compared to unary.
One pro is that is would be possible to index (or invoke, or dot off of) the result without a confusing syntax error:
x = e switch { ... }[i];
x = e switch { ... }(e);
x = e switch { ... }.P;
If the switch expression were at unary precedence, these would be difficult to explain syntax errors (unexpected token [
, (
, or .
).
One con is that the left operand cannot be subject to a unary operator:
x = -e switch {...};
x = (T)e switch {...};
At primary precedence, the negation or cast operator applies to the whole switch expression. At unary precedence, the negation or cast applies only to e
, the operand of the switch expression. I do not know which is more "natural". I suppose I could be convinced that unary precedence is better than primary.