为什么匹配表达式不会先于其他手臂报告一个包罗万象的手臂 (_) 的错误?
Why does a match expression not report an error for a catch-all arm (_) prior to other arms?
Rust 有一个名为 match
的结构,它看起来与其他语言中的 switch
非常相似。但是我观察到 match
.
的一种非常奇特的行为
let some_u32_value = 3;
match some_u32_value {
_ => (),
3 => println!("three"),
}
match
遵循提到 cases/patterns 的顺序。为什么默认(_
)的case在最上面不报错呢?不过它确实给出了警告:
warning: unreachable pattern
--> src/main.rs:5:9
|
5 | 3 => println!("three"),
| ^
|
= note: #[warn(unreachable_patterns)] on by default
开关 Java 中的类似结构不保留任何顺序,因此在其他情况之前使用 default
不是错误(忽略掉落行为)。
int x = 0;
switch (x) {
default:
System.out.println("default");
break;
case 0:
System.out.println("Zero");
}
明确地这样做有什么目的吗?
无法访问的模式严格来说不是错误,我的意思是:它不会阻止编译器 "understanding" 代码,也不会使代码不安全。
类似地,例如,在 C
中,您可以 return 引用局部变量而不会触发错误(至少在 gcc
中):
#include <stdio.h>
int* foo() {
int x = 0;
return &x;
}
int main() {
printf("%d", *foo());
return 0;
}
通常,您不应将警告视为 "oh, that's only a warning, I don't care"。警告是编译器给出的实际有用的advice/information。
我喜欢warnings中给出的定义:
A warning is often issued on recognizing a potential high-risk situation, a probable misunderstanding, degraded service or imminent failure.
因为它有助于理解错误和警告之间的区别:
- 一个错误是一个错误,
- 警告是 potential/probable 错误或有问题的事情。
在这种情况下,match
的最后一个分支是一些死代码,因此编译器会相应地报告它。
Rust 的 match
表达式比 Java switch
语句强大得多,你可以做的不仅仅是匹配数字。
特别是,它支持模式匹配,可让您根据数据的结构或包含的值匹配数据片段。当您要匹配更复杂的模式时,能够指定顺序很重要,因为模式可能会重叠。例如:
let value = Some((Some(3), "hello"));
let s = match value {
None => "Nothing there!".to_owned(),
Some((Some(3), _)) => "The number is exactly 3!".to_owned(),
Some((Some(n), _)) if n > 3 => format!("Got a number bigger than 3: {}", n),
Some((None, msg)) => format!("Message with no number: {}", msg),
Some((_, msg)) => format!("Got the message, ignore the rest: {}", msg),
_ => "Anything else?".to_owned()
};
println!("result = {}", s);
这里的最后一个案例实际上是不可能的,因为其他分支涵盖了一切。如果这不是您想要的,编译器会发出警告。
Rust 有一个名为 match
的结构,它看起来与其他语言中的 switch
非常相似。但是我观察到 match
.
let some_u32_value = 3;
match some_u32_value {
_ => (),
3 => println!("three"),
}
match
遵循提到 cases/patterns 的顺序。为什么默认(_
)的case在最上面不报错呢?不过它确实给出了警告:
warning: unreachable pattern
--> src/main.rs:5:9
|
5 | 3 => println!("three"),
| ^
|
= note: #[warn(unreachable_patterns)] on by default
开关 Java 中的类似结构不保留任何顺序,因此在其他情况之前使用 default
不是错误(忽略掉落行为)。
int x = 0;
switch (x) {
default:
System.out.println("default");
break;
case 0:
System.out.println("Zero");
}
明确地这样做有什么目的吗?
无法访问的模式严格来说不是错误,我的意思是:它不会阻止编译器 "understanding" 代码,也不会使代码不安全。
类似地,例如,在 C
中,您可以 return 引用局部变量而不会触发错误(至少在 gcc
中):
#include <stdio.h>
int* foo() {
int x = 0;
return &x;
}
int main() {
printf("%d", *foo());
return 0;
}
通常,您不应将警告视为 "oh, that's only a warning, I don't care"。警告是编译器给出的实际有用的advice/information。
我喜欢warnings中给出的定义:
A warning is often issued on recognizing a potential high-risk situation, a probable misunderstanding, degraded service or imminent failure.
因为它有助于理解错误和警告之间的区别:
- 一个错误是一个错误,
- 警告是 potential/probable 错误或有问题的事情。
在这种情况下,match
的最后一个分支是一些死代码,因此编译器会相应地报告它。
Rust 的 match
表达式比 Java switch
语句强大得多,你可以做的不仅仅是匹配数字。
特别是,它支持模式匹配,可让您根据数据的结构或包含的值匹配数据片段。当您要匹配更复杂的模式时,能够指定顺序很重要,因为模式可能会重叠。例如:
let value = Some((Some(3), "hello"));
let s = match value {
None => "Nothing there!".to_owned(),
Some((Some(3), _)) => "The number is exactly 3!".to_owned(),
Some((Some(n), _)) if n > 3 => format!("Got a number bigger than 3: {}", n),
Some((None, msg)) => format!("Message with no number: {}", msg),
Some((_, msg)) => format!("Got the message, ignore the rest: {}", msg),
_ => "Anything else?".to_owned()
};
println!("result = {}", s);
这里的最后一个案例实际上是不可能的,因为其他分支涵盖了一切。如果这不是您想要的,编译器会发出警告。