英文:
Switch expression doesn't actually seem to be an expression in Dart 3.0
问题
In Dart 3.0, switch expression is finally introduced today.
According to the official documentation,
> A switch expression is similar to a switch statement, but you can use them anywhere you can use an expression.
However, the code below doesn't compile (DartPad):
enum Color { red, blue, green }
void main() {
final color = Color.red;
switch (color) {
Color.red => "red",
Color.blue => "blue",
Color.green => "green",
};
}
though this code compiles:
enum Color { red, blue, green }
void main() {
final color = Color.red;
//binds to placeholder
final _ = switch (color) {
Color.red => "red",
Color.blue => "blue",
Color.green => "green",
};
}
void main() {
3; //expression statement
}
Why?
(This question is about the language itself rather than practical applications. So the codes above are minimal but aren't useful. Thus I added #language-lawyer
tag.)
Note, in Rust, the equivalent code compiles:
enum Color {
Red,
Blue,
Green,
}
fn main() {
let color = Color::Red;
match (color) {
Color::Red => "red",
Color::Blue => "blue",
Color::Green => "green",
};
}
英文:
In Dart 3.0, switch expression is finally introduced today.
According to the official documentation,
> A switch expression is similar to a switch statement, but you can use them anywhere you can use an expression.
However, the code below doesn't compile (DartPad):
enum Color { red, blue, green }
void main() {
final color = Color.red;
switch (color) {
Color.red => "red",
Color.blue => "blue",
Color.green => "green",
};
}
though these code compile:
enum Color { red, blue, green }
void main() {
final color = Color.red;
//binds to placeholder
final _ = switch (color) {
Color.red => "red",
Color.blue => "blue",
Color.green => "green",
};
}
void main() {
3; //expression statement
}
Why?
(This question is about the language itself rather than practical applications. So the codes above are minimal but aren't useful. Thus I added #language-lawyer
tag.)
Note, in Rust, the equivalent code compiles:
enum Color {
Red,
Blue,
Green,
}
fn main() {
let color = Color::Red;
match (color) {
Color::Red => "red",
Color::Blue => "blue",
Color::Green => "green",
};
}
答案1
得分: 2
在表达式语句的开头显式禁止使用 switch 表达式,这在语言规范中明确规定,可参考语言规范。以下是规范中的相关片段:
表达式语句的歧义
由于表达式语句的存在,switch 表达式可以出现在与 switch 语句相同的位置。这从技术上讲不是模棱两可的,但需要无限前瞻来读取值表达式,以确定语句位置的 switch 是否是语句还是表达式。
main() {
switch (some(extremely, long, expression, here)) {
_ => expression()
};
switch (some(extremely, long, expression, here)) {
case _: statement();
}
}
为了避免这种情况,我们禁止 switch 表达式出现在表达式语句的开头。这类似于对出现在表达式语句中的映射文字的现有限制。在极少数情况下,如果用户确实希望在那里使用 switch 表达式,他们可以将其括在括号中。
因此,修复方法是将表达式括在括号中:
enum Color { red, blue, green }
void main() {
final color = Color.red;
(switch (color) {
Color.red => "red",
Color.blue => "blue",
Color.green => "green",
});
}
英文:
Switch expression at a start of an expression statement is explicitly forbidden by the language spec. Here's the relevant snippet from the spec:
Expression statement ambiguity
Thanks to expression statements, a switch expression could appear in the same
position as a switch statement. This isn't technically ambiguous, but requires
unbounded lookahead to read past the value expression to the first case
in
order to tell if a switch in statement position is a statement or expression.
main() {
switch (some(extremely, long, expression, here)) {
_ => expression()
};
switch (some(extremely, long, expression, here)) {
case _: statement();
}
}
To avoid that, we disallow a switch expression from appearing at the beginning
of an expression statement. This is similar to existing restrictions on map
literals appearing in expression statements. In the rare case where a user
really wants one there, they can parenthesize it.
So the fix would be parenthesizing the expression:
enum Color { red, blue, green }
void main() {
final color = Color.red;
(switch (color) {
Color.red => "red",
Color.blue => "blue",
Color.green => "green",
});
}
ref: dart-lang/language #3061.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论