函数
在本章中,我们将学习 Rust 中的函数定义和使用。函数是 Rust 程序的基本构建块,它允许我们将代码组织成可重用的块,提高代码的可读性和可维护性。
函数定义
Rust 中使用 fn
关键字定义函数。函数名遵循 Rust 的命名约定,使用蛇形命名法(snake_case)。
rust">fn main() {println!("Hello, world!");another_function();
}fn another_function() {println!("这是另一个函数。");
}
在上面的例子中,我们定义了两个函数:main
和 another_function
。main
函数是程序的入口点,another_function
是我们自定义的函数。
函数参数
函数可以接受参数,这些参数是传递给函数的值。在函数签名中,必须声明每个参数的类型。
rust">fn main() {print_number(5);print_labeled_measurement(5, 'h');
}fn print_number(x: i32) {println!("x 的值是: {}", x);
}fn print_labeled_measurement(value: i32, unit_label: char) {println!("测量值是: {}{}", value, unit_label);
}
在这个例子中,print_number
函数接受一个 i32
类型的参数,print_labeled_measurement
函数接受一个 i32
类型和一个 char
类型的参数。
函数体中的语句和表达式
Rust 是一种基于表达式的语言。语句是执行操作但不返回值的指令,而表达式则是计算并产生一个值。
rust">fn main() {let y = 6; // 语句let x = 5; // 语句// 表达式let y = {let x = 3;x + 1 // 注意这里没有分号,这是一个表达式};println!("y 的值是: {}", y); // 输出:y 的值是: 4
}
在上面的例子中,代码块 { let x = 3; x + 1 }
是一个表达式,它计算并返回一个值。注意,表达式的最后一行没有分号,因为它是要返回的值。如果在表达式的末尾添加分号,它就变成了一个语句,不会返回值。
带返回值的函数
函数可以向调用它的代码返回值。我们在箭头(->
)后面声明返回值的类型,但不对返回值命名。
rust">fn five() -> i32 {5 // 返回值,注意没有分号
}fn main() {let x = five();println!("x 的值是: {}", x);
}
在 Rust 中,函数的返回值等同于函数体最后一个表达式的值。也可以使用 return
关键字提前从函数返回,但大多数函数隐式地返回最后一个表达式。
rust">fn plus_one(x: i32) -> i32 {x + 1 // 返回 x + 1 的值
}fn main() {let x = plus_one(5);println!("x 的值是: {}", x); // 输出:x 的值是: 6
}
如果在表达式后面加上分号,它就变成了语句,不会返回值:
rust">fn plus_one(x: i32) -> i32 {x + 1; // 错误:此函数的块不返回值
}
注释函数
可以使用文档注释来为函数提供文档:
rust">/// 将输入值加一并返回
///
/// # Examples
///
/// ```
/// let five = 5;
/// let six = plus_one(5);
/// assert_eq!(6, six);
/// ```
fn plus_one(x: i32) -> i32 {x + 1
}
函数重载
Rust 不支持函数重载(即同名但参数不同的多个函数)。每个函数名在其作用域内必须是唯一的。
闭包
Rust 有一种类似于函数的特性,称为闭包(closures)。闭包是可以保存在变量中或作为参数传递给其他函数的匿名函数。
rust">fn main() {let add_one = |x: i32| -> i32 { x + 1 };let five = 5;println!("{}+1={}", five, add_one(five));
}
闭包可以捕获其环境中的值:
rust">fn main() {let x = 4;let equal_to_x = |z| z == x;let y = 4;assert!(equal_to_x(y));
}
高阶函数
Rust 支持高阶函数,即接受函数作为参数或返回函数的函数。
rust">fn apply_twice<F>(f: F, x: i32) -> i32
whereF: Fn(i32) -> i32,
{f(f(x))
}fn main() {let add_one = |x| x + 1;let result = apply_twice(add_one, 5);println!("结果是: {}", result); // 输出:结果是: 7
}
示例程序
让我们编写一个程序,展示 Rust 中函数的各种用法:
rust">fn main() {// 调用无参数函数say_hello();// 调用带参数的函数greet("Alice");// 调用多参数函数let sum = add(5, 7);println!("5 + 7 = {}", sum);// 使用函数返回值let result = calculate_rectangle_area(4.5, 6.2);println!("矩形面积: {}", result);// 使用表达式作为函数体let squared = square(3);println!("3 的平方是: {}", squared);// 使用闭包let is_even = |n: i32| n % 2 == 0;for i in 1..=5 {println!("{} 是偶数: {}", i, is_even(i));}// 使用高阶函数let numbers = [1, 2, 3, 4, 5];let sum: i32 = numbers.iter().map(|&x| x * 2).sum();println!("数组中所有元素乘以 2 后的总和: {}", sum);
}// 无参数函数
fn say_hello() {println!("Hello!");
}// 带一个参数的函数
fn greet(name: &str) {println!("你好, {}!", name);
}// 带两个参数的函数
fn add(a: i32, b: i32) -> i32 {a + b // 返回 a + b 的值
}// 带两个浮点参数的函数
fn calculate_rectangle_area(width: f64, height: f64) -> f64 {width * height
}// 使用表达式作为函数体
fn square(n: i32) -> i32 {n * n
}
练习题
-
编写一个函数
is_palindrome
,接受一个字符串参数,判断它是否是回文(正着读和倒着读一样)。 -
编写一个函数
fibonacci
,接受一个整数 n,返回斐波那契数列的第 n 个数。 -
编写一个高阶函数
transform_array
,接受一个整数数组和一个函数作为参数,对数组中的每个元素应用该函数,并返回结果数组。 -
编写一个函数
calculate_average
,接受一个整数数组,返回其平均值。 -
编写一个闭包,用于过滤出数组中的所有偶数,并使用它来处理一个整数数组。
总结
在本章中,我们学习了:
- 如何定义和调用函数
- 函数参数和返回值的声明
- 语句和表达式的区别
- 如何使用闭包
- 高阶函数的概念和用法
函数是 Rust 程序的基本构建块,掌握函数的定义和使用对于编写清晰、模块化的代码至关重要。在下一章中,我们将学习 Rust 中的注释和文档,这对于代码的可读性和可维护性同样重要。