Rust 在编程范式上基本不做限制,Rust 没有继承,但是依然可以实现面向对象 (OOP),也支持函数式编程(FP),也支持泛型。在语法上 Rust 更多的借鉴了函数式编程的概念(FP)。可以认为,Rust 是一门面向表达式的语句,由于表达式总会返回某种类型的值,所以 Rust 是面向类型推断的。
表达式和语句
这是两个重要的编程语言的概念,表达式(expression): 一定数量的符号的集合,通常产生一个数学计算。简单的说,表达式总会产生(return)一个或一组值。
12; // 产生一个值 12 2 + 3; // 产生一个值: 5 ; // 返回一个 ()
语句的概念比较泛化,维基百科的解释:
在计算机编程语言中,一个最小的独立的命令式编程语句单元。或者是一个包含了若干上述单元的程序。语句可以包含表达式。
常见的语句有:
1、声明语句:
use std::io::{Result}
2、流程控制语句
3、表达式语句
4、宏语句
Rust 中的两种重要表达式
从宏观上看,Rust 中有两大类表达式:
;
分号表达式
{}
块表达式
;
分号在其他语言中一般都作为分隔符,但是在 Rust 中,;
有时候是一个表达式。fn bar() { ; // 返回单元类型:() }
上边的 Rust 函数
bar
,在可以编译通过的,因为,当;
处在块表达式{}
最后一行的时候,会作为表达式,返回 ()
单元类型,单元类型实际上是一个空元组。上边的代码也可以写为:fn bar() -> () { ; }
当然也可以用
return
来显式的返回:fn bar() -> () { return (); }
块表达式: 由于表达式,总要返回一个值,所以块表达式也遵循这个规则。上边的代码,
bar()
的函数体,就是一个块表达式,返回了一个单元类型;如果块表达式最后一行没有;
分号表达式,那么最后一行的值,会被直接当做返回值,所以上边的代码还可以写作:fn bar() -> () { () }
类似的,如果需要具体返回某种类型,可写作:
fn bar() -> i32 { let a = 12; let b = 13; a + b // 注意没有分号 }
Rust 中的流程控制也是表达式:
再来看一段代码:
fn bar(a: i32) { // 返回 () if a % 2 == 0 { println!("even") // println! 宏本身会返回单元类型 () } else { println!("odd") } }
假设我们设定,偶数返回 0,奇数返回 1:
fn bar(a: i32) -> i32 { let res = if a % 2 == 0 { 0 } else { 1 }; res } fn main() { println!("{}", bar(5)); // 输出 1 }
很明显,
if
可以返回一个值,因为 if 后都是块表达式。基于表达式的类型一致性
由于 Rust 是面向表达式的,所以,可以根据每个表达式的返回值,确定类型,并且将类型传递下去:
fn bar(a: i32) -> i32 { let res = if a % 2 == 0 { 0 } else { 1 }; res }
bar
是最外层的块表达式,需要一个 i32
的返回值,内部,if..else
的每个子句都是表达式,所以可以进行编译限制,让每个子句表达式都返回相同的类型。如果if..else
的某个子句表达式返回值不是 i32
就会产生编译错误:fn bar(a: i32) -> i32 { let res = if a % 2 == 0 { 0 } else { "a" // Error,编译报错 }; res }