if 表达式
Syntax
IfExpression →
if Conditions BlockExpressionNoInnerAttributes
( else ( BlockExpressionNoInnerAttributes | IfExpression ) )?
Conditions →
Expressionexcept StructExpression
| LetChain
LetChain → LetChainCondition ( && LetChainCondition )*
LetChainCondition →
Expressionexcept ExcludedConditions
| OuterAttribute* let Pattern = Scrutineeexcept ExcludedConditions
ExcludedConditions →
StructExpression
| LazyBooleanExpression
| RangeExpr
| RangeFromExpr
| RangeInclusiveExpr
| AssignmentExpression
| CompoundAssignmentExpression
if 表达式的语法是一个或多个用 && 分隔的条件操作数序列,后跟结果块、任意数量的 else if 条件和块,以及可选的尾部 else 块。
条件操作数必须是具有布尔类型的 Expression 或条件 let 匹配。
如果所有条件操作数都求值为 true 并且所有 let 模式都成功匹配其审查者,则执行结果块并跳过任何后续的 else if 或 else 块。
如果任何条件操作数求值为 false 或任何 let 模式未匹配其审查者,则跳过结果块并求值任何后续的 else if 条件。
如果所有 if 和 else if 条件都求值为 false,则执行任何 else 块。
if 表达式求值为与执行的块相同的值,如果没有块被求值则为 ()。
if 表达式在所有情况下必须具有相同的类型。
#![allow(unused)]
fn main() {
let x = 3;
if x == 4 {
println!("x is four");
} else if x == 3 {
println!("x is three");
} else {
println!("x is something else");
}
// `if` can be used as an expression.
let y = if 12 * 15 > 150 {
"Bigger"
} else {
"Smaller"
};
assert_eq!(y, "Bigger");
}
如果条件表达式发散或所有分支都发散,则 if 表达式发散。
#![allow(unused)]
fn main() {
fn diverging_condition() -> ! {
// Diverges because the condition expression diverges
if loop {} {
()
} else {
()
};
// The semicolon above is important: The type of the `if` expression is
// `()`, despite being diverging. When the final body expression is
// elided, the type of the body is inferred to ! because the function body
// diverges. Without the semicolon, the `if` would be the tail expression
// with type `()`, which would fail to match the return type `!`.
}
fn diverging_arms() -> ! {
// Diverges because all arms diverge
if true {
loop {}
} else {
loop {}
}
}
}
if let 模式
if 条件中的 let 模式允许在模式成功匹配时将新变量绑定到作用域中。
以下示例说明了使用 let 模式的绑定:
#![allow(unused)]
fn main() {
let dish = ("Ham", "Eggs");
// This body will be skipped because the pattern is refuted.
if let ("Bacon", b) = dish {
println!("Bacon is served with {}", b);
} else {
// This block is evaluated instead.
println!("No bacon will be served");
}
// This body will execute.
if let ("Ham", b) = dish {
println!("Ham is served with {}", b);
}
if let _ = 5 {
println!("Irrefutable patterns are always true");
}
}
可以使用 | 运算符指定多个模式。这与 [match 表达式]中的 | 具有相同的语义:
#![allow(unused)]
fn main() {
enum E {
X(u8),
Y(u8),
Z(u8),
}
let v = E::Y(12);
if let E::X(n) | E::Y(n) = v {
assert_eq!(n, 12);
}
}
条件链
多个条件操作数可以用 && 分隔。
类似于 && 惰性布尔表达式,每个操作数从左到右求值,直到操作数求值为 false 或 let 匹配失败,在这种情况下不求值后续操作数。
每个模式的绑定被放入作用域,以供下一个条件操作数和结果块使用。
以下是链接多个表达式、混合 let 绑定和布尔表达式、以及表达式能够引用先前表达式的模式绑定的示例:
#![allow(unused)]
fn main() {
fn single() {
let outer_opt = Some(Some(1i32));
if let Some(inner_opt) = outer_opt
&& let Some(number) = inner_opt
&& number == 1
{
println!("Peek a boo");
}
}
}
上面的代码等同于以下不使用条件链的代码:
#![allow(unused)]
fn main() {
fn nested() {
let outer_opt = Some(Some(1i32));
if let Some(inner_opt) = outer_opt {
if let Some(number) = inner_opt {
if number == 1 {
println!("Peek a boo");
}
}
}
}
}
如果任何条件操作数是 let 模式,则由于 let 审查者的歧义和优先级,任何条件操作数都不能是 || 惰性布尔运算符表达式。
Example
如果需要
||表达式,则可以使用括号。例如:#![allow(unused)] fn main() { let foo = Some(123); let condition1 = true; let condition2 = false; if let Some(x) = foo // Parentheses are required here. && (condition1 || condition2) {} }
2024 Edition differences
在 2024 版本之前,不支持 let 链。也就是说,
if表达式中不允许使用 LetChain 语法。