函数在 Rust 代码中非常普遍。我们已经使用过语言中最重要的函数之一:main
函数,它是很多程序的入口点。你也见过fn
关键字,它用来声明新函数。
Rust 代码中的函数和变量使用 snake case 规范风格。在 snake case 中,所有字母都是小写并使用下划线分隔单词。这是一个包含函数定义示例的程序:
fn main() {
println!("Hello, world!");
another_function();
}
fn another_function() {
println!("Another function.");
}
fn(i32) -> i32 { }
一个接收 i32 类型参数并返回 i32 类型参数的函数。函数也有一种 类型。
函数将一堆指令抽象为具体实体,稍后可以通过其他代码调用这个些指令,并帮助用户管理复杂性。
fn add(a: u64,b: u64) -> u64{
a+b
}
fn main(){
let a: u64 = 17;
let b = 3;
let result = add(a,b);
println!("Result {}",result);
}
在上述代码中,创建了一个名为 add
的新函数。关键字 fn
用于创建函数,随后跟着的是函数名 add
,圆括号中的a
和b
是参数,花括号中的是函数体。冒号右边是参数的类型。函数的返回类型使用->
指定,其后跟着的是类型,即u64
。如果函数无返回值,那么可以省略该类型声明。函数也有类型,我们的函数add
的类型表示为 fn (u64,u64)->u64
。类型声明也可以储存在变量中传递给其他函数。
fn add(x: u64, y: u64) -> u64 {
x + y
}
fn main() {
// 在变量中存储函数类型
let adder: fn(u64, u64) -> u64 = add;
// 将函数作为参数传递给另一个函数
execute(adder, 2, 3);
}
fn execute(f: fn(u64, u64) -> u64, x: u64, y: u64) {
let result = f(x, y);
println!("The result is: {}", result);
}
- fn (u64, u64) -> u64:这是一个函数类型的表示方式,描述了一个接受两个 u64 类型的参数,并返回一个 u64 类型结果的函数。这种表示方式可以用来定义接受此类函数为参数的函数,或者声明此类型的变量。
- 你可以将符合这个类型签名的函数赋值给一个变量。例如,如果你有一个名为 add 的函数,它接受两个 u64 类型的参数并返回它们的和(也是 u64 类型),你可以创建一个此类型的变量来引用 add 函数。
- 仔细查看
add
的函数体,会发现我们不需要像其他语言那样使用关键字return
来返回 a+b
,因为最后一个表达式会自动返回。不过Rust
中仍有关键字return
,但它用于 提前退出。函数基本上是返回值的表达式,默认情况下是()(Unit)
类型的值,这与C/C++
中的void
返回类型相似。也可以在其他函数中声明返回值,这用于你很难将某个函数(例如foo
)中的某个功能作为语句序列进行推断时。在这种情况下,你可以在本地函数bar
中提取这些行,然后在父函数foo
中定义它们。
:::info Rust 的类型推断基于 Hindly-Milner 类型系统。该系统 包含一组规则和算法,可以通过编程语言进行类型推 断。其采用了一种有效的类型推断方法,在线性时间 内执行,使它对大型程序的类型检查具有实际意义。
:::
Hindley-Milner(HM)
Hindley-Milner(HM)类型系统是一种自动类型推导算法,最初用于 ML 语言家族。这种类型系统的核心优点是能够在没有显式类型注解的情况下,自动推导出表达式的类型。它得名于两位数学家和逻辑学家:Roger Hindley 和 Robin Milner,他们分别独立发现了这一算法的基础理论。特点
- 类型推导:HM 类型系统可以自动推导程序中表达式的类型,减少了编程时需要显式指定类型的情况。
- 类型多态:支持参数多态(parametric polymorphism),也就是通常所说的泛型编程。这意味着函数可以被定义为对多种类型通用,而不需要针对每个类型重写函数。
- 类型安全:在编译时进行类型检查,可以避免很多类型错误,提高程序的安全性和可靠性。
- 无歧义性:每个表达式在给定环境中的类型都是唯一确定的,或者报错说明无法推导出类型。