语句
语句是代码块的组成部分,而代码块又是外部表达式或函数的组成部分。
声明语句
声明语句是在封闭语句块中引入一个或多个名称的语句。声明的名称可以表示新的变量或新的项。
两种声明语句分别是项声明和 let
语句。
项声明
项声明语句的语法形式与项声明在模块中的语法形式相同。在语句块中声明项会将其作用域限制为包含该语句的块。该项没有规范路径,它可能声明的任何子项也没有。但这有一个例外,即只要项和特征(如果适用)是可访问的,那么由实现定义的关联项在外部作用域中仍然是可访问的。除此之外,它在语义上与在模块内声明项是相同的。
不会隐式捕获包含函数的泛型参数、参数和局部变量。例如,inner
不能访问 outer_var
。
#![allow(unused)] fn main() { fn outer() { let outer_var = true; fn inner() { /* outer_var is not in scope here */ } inner(); } }
let
语句
语法
Let 语句 :
外部属性*let
非顶层可选模式 (:
类型 )? (=
表达式 † (else
代码块表达式) ? ) ?;
† 当指定了
else
块时,表达式不能是惰性布尔表达式,也不能以}
结尾。
let
语句引入一组新的变量,由模式给出。模式后面可以选择性地跟一个类型标注,然后要么结束,要么跟一个初始化表达式加上一个可选的 else
块。当没有给出类型标注时,编译器将推断类型,或者如果类型信息不足以进行确定性推断,则发出错误信号。变量声明引入的任何变量从声明点到封闭块作用域结束都是可见的,除非它们被另一个变量声明遮蔽。
如果没有 else
块,则模式必须是不可反驳的。如果存在 else
块,则模式可以是可反驳的。如果模式不匹配(这要求它是可反驳的),则执行 else
块。else
块必须始终发散(求值为never 类型)。
#![allow(unused)] fn main() { let (mut v, w) = (vec![1, 2, 3], 42); // The bindings may be mut or const let Some(t) = v.pop() else { // Refutable patterns require an else block panic!(); // The else block must diverge }; let [u, v] = [v[0], v[1]] else { // This pattern is irrefutable, so the compiler // will lint as the else block is redundant. panic!(); }; }
表达式语句
表达式语句是计算表达式并忽略其结果的语句。通常,表达式语句的目的是触发计算其表达式的效果。
如果仅由代码块表达式或控制流表达式组成的表达式用在允许使用语句的上下文中,则可以省略尾随分号。这可能会导致将其解析为独立语句还是解析为另一个表达式的一部分之间产生歧义;在这种情况下,它将被解析为语句。当用作语句时,带代码块的表达式的类型必须是单元类型。
#![allow(unused)] fn main() { let mut v = vec![1, 2, 3]; v.pop(); // Ignore the element returned from pop if v.is_empty() { v.push(5); } else { v.remove(0); } // Semicolon can be omitted. [1]; // Separate expression statement, not an indexing expression. }
当省略尾随分号时,结果必须是类型 ()
。
#![allow(unused)] fn main() { // bad: the block's type is i32, not () // Error: expected `()` because of default return type // if true { // 1 // } // good: the block's type is i32 if true { 1 } else { 2 }; }