Rust 函数式编程简介
Rust 是一门多范式语言,除了命令式和面向对象风格外,还积极支持函数式编程。内置特性如闭包、迭代器、强大的类型系统和默认不可变性,让你能够编写简洁、安全且富有表现力的代码。本文将解析 Rust 中函数式方法的核心概念,并展示如何在实际中应用它们。
函数式方法基础:不可变性与纯函数
函数式编程建立在两大支柱之上:数据不可变性和纯函数。Rust 鼓励不可变性——默认情况下所有变量都是不可变的。要改变值,需要显式指定 mut。
fn main() { let x = 5; // 不可变变量 // x = 6; // 编译错误 let mut y = 10; y += 5; // 允许,因为 y 是可变的 println!("x = {}, y = {}", x, y);}纯函数没有副作用,并且对于相同的参数总是返回相同的结果。Rust 允许编写这样的函数,但并不强制——你可以自由混合不同的风格。
fn add(a: i32, b: i32) -> i32 { a + b // 纯函数}闭包 (closures) —— 匿名函数
Rust 中的闭包是匿名函数,可以捕获周围作用域中的变量。它们使用语法 |参数| 函数体 定义。根据捕获方式,闭包分为三种:通过引用 (&T)、通过可变引用 (&mut T) 和通过值 (T)。
简单闭包示例
fn main() { let factor = 2; let multiply = |x: i32| x * factor; println!("{}", multiply(10)); // 20}带可变捕获的闭包
fn main() { let mut counter = 0; let mut increment = || { counter += 1; counter }; println!("{}", increment()); // 1 println!("{}", increment()); // 2}闭包广泛用于迭代器以及将行为传递给高阶函数。
迭代器与函数式链式调用
Rust 中的迭代器是最强大的函数式抽象之一。你可以构建由 map、filter、fold 等方法组成的链式调用,而不是使用循环。迭代器是惰性的——计算仅在调用消费者(例如 collect 或 for_each)时才会执行。
示例:过滤与转换
fn main() { let numbers = vec![1, 2, 3, 4, 5, 6]; let result: Vec<i32> = numbers .iter() .filter(|&x| x % 2 == 0) // 保留偶数 .map(|x| x * x) // 求平方 .collect(); println!("{:?}", result); // [4, 16, 36]}折叠 (fold) —— 值的累加
fn main() { let numbers = vec![1, 2, 3, 4]; let sum = numbers.iter().fold(0, |acc, x| acc + x); println!("总和: {}", sum); // 10}迭代器使代码更具声明性:你描述做什么,而不是怎么做。这降低了出错的可能性并提高了可读性。
模式匹配 (pattern matching)
match 结构是 Rust 函数式风格的核心元素。它允许你解构复杂的数据结构、处理 Option 和 Result 的变体,并编写穷尽性检查。
基本示例
fn describe_number(n: i32) -> &'static str { match n { 0 => "零", 1 | 2 => "小数字", 3..=10 => "中等数字", _ if n < 0 => "负数",\