ifif let表达式

if-expr.md
commit: d23f9da8469617e6c81121d9fd123443df70595d
本章译文最后维护日期:2021-5-6

if表达式

句法
IfExpression :
   if Expression排除结构体表达式 BlockExpression
   (else ( BlockExpression | IfExpression | IfLetExpression ) )?

if表达式是程序控制中的一个条件分支。if表达式的句法是一个条件操作数(operand)后紧跟一个块,再后面是任意数量的 else if条件表达式和块,最后是一个可选的尾部 else块。 条件操作数的类型必须是布尔型。如果条件操作数的求值结果为 true,则执行紧跟的块,并跳过后续的 else if块或 else块。 如果条件操作数的求值结果为 false,则跳过紧跟的块,并按顺序求值后续的 else if条件表达式。 如果所有 if条件表达式和 else if条件表达式的求值结果均为 false,则执行 else块。 if表达式的求值结果就是所执行的块的返回值,或者如果没有块被求值那 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"); } let y = if 12 * 15 > 150 { "Bigger" } else { "Smaller" }; assert_eq!(y, "Bigger"); }

if let表达式

句法
IfLetExpression :
   if let Pattern = Expression排除结构体表达式和惰性布尔运算符表达式 BlockExpression
   (else ( BlockExpression | IfExpression | IfLetExpression ) )?

if let表达式在语义上类似于 if表达式,但是代替条件操作数的是一个关键字 let,再后面是一个模式、一个 = 和一个检验对象(scrutinee)操作数。 如果检验对象操作数的值与模式匹配,则执行相应的块。 否则,如果存在 else块,则继续处理后面的 else块。和 if表达式一样,if let表达式也可以有返回值,这个返回值是由被求值的块确定。

#![allow(unused)] fn main() { let dish = ("Ham", "Eggs"); // 此主体代码将被跳过,因为该模式被反驳 if let ("Bacon", b) = dish { println!("Bacon is served with {}", b); } else { // 这个块将被执行。 println!("No bacon will be served"); } // 此主体代码将被执行 if let ("Ham", b) = dish { println!("Ham is served with {}", b); } if let _ = 5 { println!("不可反驳型的模式总是会匹配成功的"); } }

if表达式和 if let表达式能混合使用:

#![allow(unused)] fn main() { let x = Some(3); let a = if let Some(1) = x { 1 } else if x == Some(2) { 2 } else if let Some(y) = x { y } else { -1 }; assert_eq!(a, 3); }

if let表达式等价于match表达式,例如:

if let PATS = EXPR { /* body */ } else { /*else */ }

is equivalent to

match EXPR { PATS => { /* body */ }, _ => { /* else */ }, // 如果没有 else块,这相当于 `()` }

可以使用操作符 | 指定多个模式。 这与匹配(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); } }

if let表达式不能是惰性布尔运算符表达式。 使用惰性布尔运算符的效果是不明确的,因为 Rust 里一个新特性(if-let执行链(if-let chains)的实现-请参阅eRFC 2947)正被提上日程。 当确实需要惰性布尔运算符表达式时,可以像下面一样使用圆括号来实现:

// Before... if let PAT = EXPR && EXPR { .. } // After... if let PAT = ( EXPR && EXPR ) { .. } // Before... if let PAT = EXPR || EXPR { .. } // After... if let PAT = ( EXPR || EXPR ) { .. }