语句
语句 是 块 的组成部分,而块又是 表达式 或 函数 的组成部分。这同样形成了 '树' 的组织结构。
声明语句
声明语句 引入一个或多个 名称 到闭合语句块中。 声明的名称可能表示新变量或新 条目 。
声明语句有两种类型: let
语句和条目声明。
条目声明
条目声明语句 的语法形式与 模块 中的 条目声明 相同。 在语句块中声明一个条目,将被限制在包含该语句的块作用域中。 该条目不会被赋予 规范路径 ,也不会声明任何子条目。 唯一的例外是通过 实现 定义的关联条目,只要该条目和 (如果适用) trait 可访问,则可以在外部访问。 否则,与在模块中声明该条目的含义相同。
不会隐式捕获包含它的函数的泛型参数、参数和局部变量。
例如, inner
无法访问 outer_var
。
#![allow(unused)] fn main() { fn outer() { let outer_var = true; fn inner() { /* outer_var 不在作用域中。 */ } inner(); } }
let
语句
语法
Let语句 :
外围属性*let
模式非顶层项 (:
类型 )? (=
表达式 † (else
块表达式) ? ) ?;
† 当指定了
else
块时,表达式不能是 惰性布尔表达式 ,也不能以}
结尾。
let
语句引入了一组由 模式 给定的新 变量 。
模式可选地后跟一个类型注释,然后以初始化表达式结束,或者跟随可选的 else
块。
当没有给出类型注释时,编译器将推断类型,如果没有足够的类型信息进行明确推断,则会发出错误信号。
任何由变量声明引入的变量在声明处到包含块范围的结尾处之间可见,除非该变量被另一个同名变量声明隐藏。
如果不存在 else
块,则模式必须是不可拒绝的。
如果存在 else
块,则模式可以是可拒绝的。
如果模式不匹配 (这需要它是可拒绝的) ,则执行 else
块。
else
块必须始终发散 (求值为 永不类型 )。
译注:'拒绝' 和 '不可拒绝' 表示模式是否能够在任何情况下都成功匹配。 '发散' 指的是一个表达式是否无法正常终止并返回值。
#![allow(unused)] fn main() { let (mut v, w) = (vec![1, 2, 3], 42); // 绑定可以是可变或常量 let Some(t) = v.pop() else { // 可拒绝的模式需要一个 else 块 panic!(); // else 块必须发散 }; let [u, v] = [v[0], v[1]] else { // 这个模式是不可拒绝的,所以编译器会认为 else 块是冗余的进行代码分析检查 panic!(); }; }
表达式语句
表达式语句 是指仅执行表达式并忽略其结果的语句。 通常,此表达式语句的是为了触发其表达式的副作用。
如果一个表达式只包含一个块表达式或控制流表达式,并且在允许语句的上下文中,则可以省略分号。 这会有可能在解析时,是作为独立语句,还是作为另一个表达式的一部分,而产生歧义。这时,会被解析为语句。 当 块表达式 作为语句时,其类型必须是单元类型。
#![allow(unused)] fn main() { let mut v = vec![1, 2, 3]; v.pop(); // 忽略 pop 返回值 if v.is_empty() { v.push(5); } else { v.remove(0); } // 分号可以省略。 [1]; // 是独立的表达式语句。 }
if 表达式语句省略了结尾的分号,其结果类型为 ()
。
#![allow(unused)] fn main() { // 错误: 块表达式类型是 i32, 不是 () // Error: expected `()` because of default return type // if true { // 1 // } // 成功: 块表达式类型是 i32 if true { 1 } else { 2 }; }