返回首页

函数式 Rust:不可变性和迭代器

本文解释了 Rust 中函数式风格的优势:不可变性代替变异、声明式迭代器代替循环、用 Result 和 Option 进行显式错误处理。提供了代码示例和针对中高级开发者的建议。

Rust 中的干净代码:无变异函数式方法
Advertisement 728x90

Rust中的函数式风格:不可变性、声明式代码与错误处理

Rust中的函数式编程解决了命令式和面向对象风格的常见问题:可变性、命令式循环和隐式错误处理。代码不是通过改变状态来构建,而是基于不可变转换、声明式操作以及ResultOption等显式类型。这使得程序更可预测且不易出错。

Rust默认不可变,鼓励开发者重新思考熟悉的模式。函数式风格使用迭代器、函数组合和模式匹配来编写简洁、无副作用的代码。

不可变性优于可变性

可变变量会创建隐藏依赖:值会意外改变,使调试复杂化。在命令式代码中,mut x变量在声明和使用之间的任何时刻都可能被修改。

Google AdInline article slot
fn my_function(num: i32) -> i32 {
    let mut x = num;
    // ...30多行代码...
    x += 96;
    // ...50多行代码...
    x
}

这里,原始值被破坏,由于潜在的中间更改,结果不可预测。不可变性解决了这个问题:创建新值而不是修改旧值。

let x = 10;
let new_x = process(x); // x保持不变

在Rust中,不可变是常态。可变需要显式的mut,但函数式风格尽量减少其使用:

  • 检查是否可以使用迭代器或map不可变地解决问题。
  • 如果可变不可避免,将其隔离在尽可能小的块中。
  • 优先使用clone或借用进行数据传播。

这降低了竞态条件风险并简化了并发。

Google AdInline article slot

声明式与命令式代码

命令式代码描述执行步骤:循环、条件、突变。函数式代码描述期望的结果。要获取0到9的数字平方,命令式版本需要向量和push:

let mut squares = Vec::new();
for num in 0..10 {
    squares.push(num * num);
}

声明式方法使用迭代器链:

let squares: Vec<i32> = (0..10)
    .map(|x| x * x)
    .collect();

声明式风格的优势:

Google AdInline article slot
  • 代码更少:迭代器链替代循环。
  • 不可变性:无集合突变。
  • 可组合性:函数易于组合。
  • 并发性.par_iter()无需锁即可实现多线程。

Rust中的迭代器是惰性的:map直到collectfor_each才执行,优化了内存。

显式错误处理

其他语言中的异常隐藏错误:try-catch允许忽略类型和上下文。在Rust中,Result<T, E>?要求显式处理或传播。

使用unwrap的错误示例:

old_toaster().unwrap(); // 错误时恐慌

正确方法使用matchmap_err

let toast = match old_toaster() {
    Ok(t) => t,
    Err(e) => {
        eprintln!("错误: {}", e);
        std::process::exit(1);
    }
};

处理技巧:

  • match用于完全控制。
  • map_err用于错误转换。
  • ?仅在调用者处理时使用。
  • 使用anyhowthiserror等库以方便。

这防止了生产环境中的恐慌,并在编译时强制考虑错误。

消除隐式空值

在命令式语言中,null无处不在,导致NullPointerException。Rust使用Option<T>:显式的Some(value)None

let maybe_candies: Option<Vec<Candy>> = get_candies();
let candies = match maybe_candies {
    Some(c) => c,
    None => Vec::new(),
};

模式匹配确保两种情况都得到处理。编译器不会忽略None

关键要点

  • 默认不可变性减少了状态变化引起的错误。
  • 迭代器和map替代循环,使代码声明式。
  • Result和Option强制显式错误和空值处理。
  • 函数组合简化了测试和重构。
  • 函数式风格适用于Rust中80%的任务;可变性仅用于IO或性能热点。

— Editorial Team

Advertisement 728x90

继续阅读