在Dart 3.0中,开关表达式实际上似乎不是表达式

ny6fqffe  于 2023-05-11  发布在  其他
关注(0)|答案(1)|浏览(189)

在Dart 3.0中,今天终于引入了 switch expression
根据官方文件

  • switch表达式类似于switch语句,但您可以在任何可以使用表达式的地方使用它们。*

但是,下面的代码无法编译(DartPad):

enum Color { red, blue, green }

void main() {
  final color = Color.red;
  switch (color) {
    Color.red => "red",
    Color.blue => "blue",
    Color.green => "green",
  };
}

虽然这些代码编译:

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
}

为什么?
(This问题是语言本身,而不是实际应用。因此,上面的代码是最小的,但不是有用的。因此我添加了#language-lawyer标签。)
注意,在Rust中,等效的代码编译为:

enum Color {
    Red,
    Blue,
    Green,
}

fn main() {
    let color = Color::Red;
    match (color) {
        Color::Red => "red",
        Color::Blue => "blue",
        Color::Green => "green",
    };
}
ljsrvy3e

ljsrvy3e1#

语言规范明确禁止在表达式语句的开头使用开关表达式。以下是规范中的相关片段:

表达式语句歧义

由于表达式语句,switch表达式可以出现在与switch语句相同的位置。这在技术上并不模糊,但需要无限的前瞻来读取值表达式到第一个case,以判断语句位置中的开关是语句还是表达式。

main() {
  switch (some(extremely, long, expression, here)) {
    _ => expression()
  };

  switch (some(extremely, long, expression, here)) {
    case _: statement();
  }
}

为了避免这种情况,我们不允许switch表达式出现在表达式语句的开头。这类似于对出现在表达式语句中的Map文字的现有限制。在极少数情况下,用户真的想要一个,他们可以括号它。
因此,修复方法是将表达式用括号括起来:

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 .

相关问题