Switch 表达式在 Dart 3.0 中似乎不是一个实际的表达式。

huangapple go评论64阅读模式
英文:

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",
  });
}

参考:dart-lang/language #3061

英文:

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.

huangapple
  • 本文由 发表于 2023年5月11日 12:10:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76224096.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定