====== 闭包、迭代器与模块系统 ======
===== 闭包(Closure) =====
闭包是可以捕获环境的匿名函数。
==== 闭包语法 ====
fn main() {
// 完整语法
let add_one = |x: i32| -> i32 { x + 1 };
// 简写(省略类型注解)
let add_two = |x| x + 2;
// 多行闭包
let multiply = |x, y| {
let result = x * y;
println!("{} x {} = {}", x, y, result);
result
};
println!("{}", add_one(5)); // 6
println!("{}", add_two(5)); // 7
println!("{}", multiply(3, 4)); // 12
}
==== 捕获环境 ====
闭包可以捕获其定义作用域中的变量:
fn main() {
let x = 4;
let equal_to_x = |z| z == x; // 捕获 x
println!("{}", equal_to_x(4)); // true
}
==== 闭包捕获方式 ====
闭包通过三种方式捕获变量:
* ''FnOnce'' - 取得所有权,只能调用一次
* ''FnMut'' - 可变借用
* ''Fn'' - 不可变借用
fn main() {
let s = String::from("hello");
// Fn:不可变借用
let print = || println!("{}", s);
print();
println!("仍可用: {}", s); // OK
// FnMut:可变借用
let mut s2 = String::from("hello");
let mut append = || s2.push_str(" world");
append();
// FnOnce:取得所有权
let s3 = String::from("hello");
let consume = || drop(s3);
consume();
// println!("{}", s3); // 编译错误:s3 已被移动
}
==== 闭包作为参数 ====
fn do_twice(f: F, x: i32) -> i32
where
F: Fn(i32) -> i32,
{
f(x) + f(x)
}
fn main() {
let result = do_twice(|x| x * 2, 5);
println!("{}", result); // 20 (10 + 10)
}
===== 迭代器(Iterator) =====
迭代器是 Rust 中处理序列的强大工具。
==== 基本使用 ====
fn main() {
let v = vec![1, 2, 3, 4, 5];
// for 循环隐式使用迭代器
for i in &v {
println!("{}", i);
}
// 显式创建迭代器
let iter = v.iter(); // 不可变引用迭代器
for i in iter {
println!("{}", i);
}
}
==== 消耗型适配器 ====
消耗迭代器的方法:
fn main() {
let v = vec![1, 2, 3, 4, 5];
// sum - 求和
let sum: i32 = v.iter().sum();
println!("{}", sum); // 15
// count - 计数
let count = v.iter().count();
println!("{}", count); // 5
// collect - 收集到集合
let doubled: Vec = v.iter().map(|x| x * 2).collect();
println!("{:?}", doubled); // [2, 4, 6, 8, 10]
}
==== 迭代器适配器 ====
链式调用来转换迭代器:
fn main() {
let v = vec![1, 2, 3, 4, 5, 6];
// map - 映射每个元素
// filter - 过滤元素
// take - 取前 n 个
let result: Vec = v.iter()
.map(|x| x * 2) // 全部乘以 2
.filter(|x| x % 3 == 0) // 保留 3 的倍数
.take(3) // 取前 3 个
.collect();
println!("{:?}", result); // [6, 12]
// 链式计算:过滤出偶数,平方,求和
let sum: i32 = (1..=10)
.filter(|x| x % 2 == 0)
.map(|x| x * x)
.sum();
println!("{}", sum); // 2^2 + 4^2 + 6^2 + 8^2 + 10^2 = 220
}
==== 自定义迭代器 ====
struct Counter {
count: u32,
}
impl Counter {
fn new() -> Counter {
Counter { count: 0 }
}
}
impl Iterator for Counter {
type Item = u32;
fn next(&mut self) -> Option {
self.count += 1;
if self.count <= 5 {
Some(self.count)
} else {
None
}
}
}
fn main() {
let sum: u32 = Counter::new()
.zip(Counter::new().skip(1))
.map(|(a, b)| a * b)
.filter(|x| x % 3 == 0)
.sum();
println!("{}", sum);
}
===== 模块系统 =====
==== crate 和模块 ====
Rust 的组织单元:
* **crate** - 一个库或可执行项目的根
* **模块(mod)** - 组织代码的层级结构
// src/main.rs
mod front_of_house;
fn main() {
front_of_house::hosting::add_to_waitlist();
}
// src/front_of_house.rs(或 src/front_of_house/mod.rs)
pub mod hosting {
pub fn add_to_waitlist() {
println!("已添加候补");
}
}
==== 路径引用 ====
mod restaurant {
pub mod hosting {
pub fn add_to_waitlist() {}
fn seat_at_table() {} // 默认私有
}
mod serving {
fn take_order() {}
}
}
fn main() {
// 绝对路径
crate::restaurant::hosting::add_to_waitlist();
// 相对路径
use restaurant::hosting;
hosting::add_to_waitlist();
}
==== use 关键字 ====
use std::collections::{HashMap, HashSet}; // 嵌套导入
use std::io::{self, Write}; // self 表示模块本身
use std::fmt::Result; // 导入到当前作用域
// 重命名
use std::collections::HashMap as Map;
fn main() {
let mut map = HashMap::new();
map.insert(1, 2);
let mut map2 = Map::new();
map2.insert("a", "b");
}
==== 模块可见性 ====
^ 修饰符 ^ 可见性 ^
| ''pub'' | 公开可见 |
| (无修饰) | 私有,仅当前模块及其子模块可见 |
| ''pub(crate)'' | 整个 crate 内可见 |
| ''pub(super)'' | 上一级模块可见 |
| ''pub(in path)'' | 指定路径可见 |
pub fn public_func() {}
fn private_func() {}
pub(crate) fn crate_visible() {}
pub(super) fn parent_visible() {}
==== 外部依赖 ====
在 ''Cargo.toml'' 中添加:
[dependencies]
serde = { version = "1.0", features = ["derive"] }
rand = "0.8"
在代码中使用:
use rand::Rng;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct User {
name: String,
age: u8,
}
fn main() {
let secret_number = rand::thread_rng().gen_range(1..=100);
println!("随机数: {}", secret_number);
}
===== 本章小结 =====
* 闭包是捕获环境的匿名函数,三种捕获方式:''Fn''、''FnMut''、''FnOnce''
* 迭代器提供 lazy 的序列操作,适配器可链式调用
* ''collect()''、''map()''、''filter()'' 等是常用迭代器方法
* 模块系统组织代码:''mod''、''use''、''pub''
* 使用 ''pub'' 控制可见性
* ''Cargo.toml'' 管理外部依赖