有些语言必须要分号,不然会报错,比如 C/C++, Java.
有些语言分号是可选的,例如 JavaScript.
在 Rust 中,分号不仅仅是分割符,而是区分语句与表达式的符号。
看两段代码:
/// # 判断两个变量是否相等
/// 参数类型:空
/// 返回类型:单元字符
fn sum1() -> () {
let a = 1;
let b = 2;
a + b;
}
/// # 两数之和
/// 参数类型:(i32, i32)
/// 返回类型:i32
fn sum2(a:i32, b:i32) -> i32 {
a + b
}
首先来看,单元类型是指其值为空的值,含义为“没有什么特殊价值的值”,当它作为返回类型时候表示该函数无返回值。
- 在函数
sum1
的声明中,返回值为单元类型,表示该函数无返回值。 - 在函数
sum2
的声明中,返回值为i32
, 表示返回值为一个 32 位整型。
那么函数体内是如何实现上述返回类型的声明的呢?
首先来看 sum2
的唯一一行代码:a + b
, 它没有分号,因此被 Rust 编译器识别为一个用于求值的表达式,又因为这一行代码处于函数的最后一行,因此该表达式计算的结果被充当与函数的返回值。
之后来灌输 Rust 中的语句的概念:语句是一些要执行的操作和能产生副作用的表达式。语句分为两种:1. 声明语句;2. 表达式语句。
再来看 sum1
, 它有三行代码,第一第二行相似,均为声明语句,顾名思义,这两行语句声明了两个变量 a
, b
, 其值分别为 1
,2
. 之后第三行代码为一个表达式语句, 它与 sum2
唯一的不同在于最后多了一个分号,这导致了 sum1
的返回值为一个单元类型。
那么,为什么加上分号后会返回两个完全不同的类型呢?
因为,Rust 的解析器如果遇到分号,则会继续向后执行,以 a + b;
为例,编辑器计算完 a+b
后,随后向下一行执行代码,但是下一行为空,则补上单元值 ()
.
综上,分号在 Rust 中的作用为区分表达式和语句,若有分号,则为语句,执行完语句后继续向后执行;若无分号,则为表达式,执行完后作为该作用域的结果返回。
因此,我认为:
Rust 中,分号既不是可选的,也不是必须的,这种设计足以让我们按需写出优雅的代码。