Home

Rust 2.5 if

10 Jan 2015 by LelouchHe

原文链接

Rust的if并不是很复杂,但它更像是动态语言中的if,而不是传统的系统编程语言中的那样.所以,我们下面介绍它,体会下其中的区别.

if是一个更广泛概念”branch”的特殊形式.名字来源于树枝(“branch in a tree”): 一个决策判断点,不同的选择带来不同的分支走向.

一种情况下,一个选择带来2个分支:

let x = 5;
if x == 5 {
    println!("x is five!");
}

如果改变了x的值,就不会输出那句话了.具体而言,如果if后面的表达式为真(true),语句执行,否则,就不执行.

如果非真(false)的时候,要执行某些语句的话,使用else:

let x = 5;
if x == 5 {
    println!("x is five!");
} else {
    println!("x is not five :(");
}

这些都很常规.然而,你还可以这样做:

let x = 5;
let y = if x == 5 {
    10
} else {
    15
}; // y: i32

我们也可以这样来写(这样更好):

let x = 5;
let y = if x == 5 { 10 } else { 15 } // y: i32 

这说明了2点: Rust是基于表达式(expression-based)的语言;分号(“;”)和其他基于大括号与分号的语言不同.这2点是相关的.

表达式(expression)与语句(statement)

Rust是基于表达式的语言.除了2种语句类型之外,其他都是表达式类型.

他们的区别是什么?表达式返回一个值(value),但语句不返回.很多语言里,if是一个语句,所以类似let x = if ...是没有意义的.但在Rust中,if是表达式,会返回值.我们就是用这个值来初始化y的绑定的.

另外,绑定是Rust的2种语句之一.正式的名字应该是声明语句(declaration statement).到目前为止,let是唯一一种声明语句.我们再来看看其他的.

很多语言里,变量绑定被当作表达式,而不是语句.比如Ruby中:

x = y = 5

但在Rust中,使用let来进行绑定不是一个表达式.以下写法会导致编译错误:

let x = (let y = 5); // expected identifier, found keyword `let`

编译器告诉我们它预期看到一个表达式,但let只能是语句,而不是表达式.

注意,对一个已经绑定的变量赋值(比如 y = 5)仍然是一个表达式,虽然这个表达式的值不是很有用.不像C语言,在C语言中,赋值表达式的值是被赋值的值(比如刚才那个例子里的5),但在Rust中,赋值表达式返回的是unit类型()(我们稍后会讲)(译者: 这个类型就是”()”,叫做unit类型)

第二种语句是表达式语句(expression statement).主要是讲表达式转变为语句.具体来说,Rust的语言是一条语句接一条语句的.这就是说,我们使用分号(“;”)来把表达式分隔开来.Rust很像那些要求每句结尾都用分号隔开的语言,而且你在几乎每行Rust代码后,都会看到分号的存在.

为什么是”几乎”呢?其实,你刚才已经看到了:

let x = 5;
let y: i32 = if x == 5 { 10 } else { 15 };

注意,我在这里添加了类型标注,说明y的类型需要是整型.

这个和下面这个是不同的,下面这个会编译失败:

let x = 5;
let y: i32 = if x == 5 { 10; } else { 15;};

注意10和15后面的分号.Rust会显示如下错误:

error: mismatched type: expected `i32`, found `()`

我们预期类型是整型,但却得到了().()类型读作”unit”类型,是Rust类型系统中一个特殊类型.Rust中,()不能赋值给的i32的值.()只能赋值给()类型的变量,所以不是很有用.还记得我们说过语句不返回值么?这就是这个类型的作用了,分号将任意表达式转变为语句,丢弃掉返回值,并返回unit类型.

还有一个地方你在行尾看不到分号,那就是下一节内容: 函数