Rust从入门到精通之入门篇:6.函数

发布于:2025-03-26 ⋅ 阅读:(29) ⋅ 点赞:(0)

函数

在本章中,我们将学习 Rust 中的函数定义和使用。函数是 Rust 程序的基本构建块,它允许我们将代码组织成可重用的块,提高代码的可读性和可维护性。

函数定义

Rust 中使用 fn 关键字定义函数。函数名遵循 Rust 的命名约定,使用蛇形命名法(snake_case)。

fn main() {
    println!("Hello, world!");
    another_function();
}

fn another_function() {
    println!("这是另一个函数。");
}

在上面的例子中,我们定义了两个函数:mainanother_functionmain 函数是程序的入口点,another_function 是我们自定义的函数。

函数参数

函数可以接受参数,这些参数是传递给函数的值。在函数签名中,必须声明每个参数的类型。

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 是一种基于表达式的语言。语句是执行操作但不返回值的指令,而表达式则是计算并产生一个值。

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 } 是一个表达式,它计算并返回一个值。注意,表达式的最后一行没有分号,因为它是要返回的值。如果在表达式的末尾添加分号,它就变成了一个语句,不会返回值。

带返回值的函数

函数可以向调用它的代码返回值。我们在箭头(->)后面声明返回值的类型,但不对返回值命名。

fn five() -> i32 {
    5 // 返回值,注意没有分号
}

fn main() {
    let x = five();
    println!("x 的值是: {}", x);
}

在 Rust 中,函数的返回值等同于函数体最后一个表达式的值。也可以使用 return 关键字提前从函数返回,但大多数函数隐式地返回最后一个表达式。

fn plus_one(x: i32) -> i32 {
    x + 1 // 返回 x + 1 的值
}

fn main() {
    let x = plus_one(5);
    println!("x 的值是: {}", x); // 输出:x 的值是: 6
}

如果在表达式后面加上分号,它就变成了语句,不会返回值:

fn plus_one(x: i32) -> i32 {
    x + 1; // 错误:此函数的块不返回值
}

注释函数

可以使用文档注释来为函数提供文档:

/// 将输入值加一并返回
///
/// # Examples
///
/// ```
/// let five = 5;
/// let six = plus_one(5);
/// assert_eq!(6, six);
/// ```
fn plus_one(x: i32) -> i32 {
    x + 1
}

函数重载

Rust 不支持函数重载(即同名但参数不同的多个函数)。每个函数名在其作用域内必须是唯一的。

闭包

Rust 有一种类似于函数的特性,称为闭包(closures)。闭包是可以保存在变量中或作为参数传递给其他函数的匿名函数。

fn main() {
    let add_one = |x: i32| -> i32 { x + 1 };
    
    let five = 5;
    println!("{}+1={}", five, add_one(five));
}

闭包可以捕获其环境中的值:

fn main() {
    let x = 4;
    
    let equal_to_x = |z| z == x;
    
    let y = 4;
    assert!(equal_to_x(y));
}

高阶函数

Rust 支持高阶函数,即接受函数作为参数或返回函数的函数。

fn apply_twice<F>(f: F, x: i32) -> i32
where
    F: 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 中函数的各种用法:

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
}

练习题

  1. 编写一个函数 is_palindrome,接受一个字符串参数,判断它是否是回文(正着读和倒着读一样)。

  2. 编写一个函数 fibonacci,接受一个整数 n,返回斐波那契数列的第 n 个数。

  3. 编写一个高阶函数 transform_array,接受一个整数数组和一个函数作为参数,对数组中的每个元素应用该函数,并返回结果数组。

  4. 编写一个函数 calculate_average,接受一个整数数组,返回其平均值。

  5. 编写一个闭包,用于过滤出数组中的所有偶数,并使用它来处理一个整数数组。

总结

在本章中,我们学习了:

  • 如何定义和调用函数
  • 函数参数和返回值的声明
  • 语句和表达式的区别
  • 如何使用闭包
  • 高阶函数的概念和用法

函数是 Rust 程序的基本构建块,掌握函数的定义和使用对于编写清晰、模块化的代码至关重要。在下一章中,我们将学习 Rust 中的注释和文档,这对于代码的可读性和可维护性同样重要。