TocHomeGithubInfo

quick-references/rust

Rust 中进行函数式编程

在 Rust 中进行函数式编程(Functional Programming, FP)是可行的,尽管 Rust 不是纯函数式语言(如 Haskell),但它提供了许多函数式编程的特性。

1. 使用不可变数据(Immutability)

函数式编程强调不可变性,Rust 默认变量是不可变的(除非用 mut 声明)。

let x = 5;      // 不可变
// x = 6;       // 错误,不能修改不可变变量
let mut y = 10; // 可变
y = 20;         // 可以修改
  • 尽量使用不可变变量(let 不加 mut)。
  • 需要修改数据时,考虑返回新数据而不是原地修改。

2. 高阶函数(Higher-Order Functions)

Rust 支持将函数作为参数或返回值(高阶函数)。

// 函数作为参数
fn apply_twice(f: impl Fn(i32) -> i32, x: i32) -> i32 {
    f(f(x))
}

let square = |x| x * x;
println!("{}", apply_twice(square, 3)); // 输出 81 (3^2^2)

3. 闭包(Closures)

闭包(匿名函数)可以捕获环境变量,是函数式编程的重要工具。

let factor = 2;
let multiply = |x| x * factor; // 捕获外部的 factor
println!("{}", multiply(5));   // 输出 10

闭包类型

  • Fn:不可变借用(&T)。
  • FnMut:可变借用(&mut T)。
  • FnOnce:获取所有权(T)。

4. 迭代器(Iterators)

Rust 的迭代器是惰性的(lazy),支持链式调用,类似函数式语言的 map/filter/reduce

let numbers = vec![1, 2, 3, 4, 5];

// 链式调用:过滤 -> 映射 -> 求和
let sum: i32 = numbers.iter()
    .filter(|&x| x % 2 == 0)  // 过滤偶数
    .map(|x| x * x)           // 平方
    .sum();                   // 求和

println!("{}", sum); // 输出 2*2 + 4*4 = 20

常用迭代器方法

方法 作用 示例
map 转换元素 `.map(
filter 过滤元素 `.filter(
fold 累积计算(reduce) `.fold(0,
collect 收集为集合 .collect::<Vec<_>>()
take 取前 n 个元素 .take(5)

5. 模式匹配(Pattern Matching)

Rust 的 matchif let 是强大的模式匹配工具。

fn factorial(n: u32) -> u32 {
    match n {
        0 | 1 => 1,          // 匹配 0 或 1
        _ => n * factorial(n - 1), // 递归
    }
}

println!("{}", factorial(5)); // 输出 120

if let 表达式是 match 的一个语法糖,用于只关心一个特定模式的匹配。

它允许你简洁地检查一个值是否匹配某个模式,如果匹配则执行相应的代码。

fn process_option(option: Option<i32>) {
    if let Some(value) = option {
        println!("Value: {}", value);
    } else {
        println!("No value");
    }
}

6. Option 和 Result 的链式处理

Rust 的 OptionResult 支持函数式风格的组合操作:

// Option 的链式处理
let result = Some(5)
    .map(|x| x * 2)      // Some(10)
    .filter(|x| x > 8)   // Some(10)
    .and_then(|x| Some(x + 1)); // Some(11)

// Result 的错误处理
let parse_result = "123"
    .parse::<i32>()
    .map(|x| x * 2)
    .map_err(|e| format!("Parse failed: {}", e));

7. 递归(Recursion)

函数式编程常用递归替代循环,但 Rust 默认不优化递归(注意可能会栈溢出)

fn sum_list(list: &[i32]) -> i32 {
    match list {
        [] => 0,
        [head, tail @ ..] => head + sum_list(tail), // 递归
    }
}

println!("{}", sum_list(&[1, 2, 3])); // 输出 6

8. 纯函数(Pure Functions)

纯函数(无副作用、输出仅依赖输入)在 Rust 中可通过以下方式实现:

  • 避免修改外部状态。
  • 不适用 static mut 或全局可变变量。
  • 返回新数据而非修改输入。

9. 函数组合(Function Composition)

Rust 没有原生 >><< 组合操作符,但可以手动实现:

fn compose<A, B, C>(f: impl Fn(B) -> C, g: impl Fn(A) -> B) -> impl Fn(A) -> C {
    move |x| f(g(x))
}

let add_one = |x| x + 1;
let square = |x| x * x;
let add_then_square = compose(square, add_one);
println!("{}", add_then_square(2)); // (2+1)^2 = 9

10. 不可变数据结构

使用 ArcRc 或第三方库(如 im)实现持久化数据结构(Persistent Data Structures),避免拷贝开销。

use std::sync::Arc;
let vec1 = Arc::new(vec![1, 2, 3]);
let vec2 = Arc::clone(&vec1); // 共享数据