Functional Language Features Iterators and Closures
Closures: Anonymous Functions that Capture Their Environment
闭包:可以捕获其所在环境的匿名函数
闭包的定义
|parameters: type, ...| -> type {
code
}
参数和返回值的类型可以不用显示标注,编译器会自动推断
可以将闭包赋值给变量调用
let f = |num: i32| {
num
};
如何让 struct 持有闭包
需要泛型和 Fn Trait
struct Cacher<T>
where
T: Fn(i32) -> i32,// 参数和返回值
{
cal: T,
value: Option<i32>,
}
impl<T> Cacher<T>
where
T: Fn(i32) -> i32,
{
fn new(x: T) -> Cacher<T> {
Cacher {
cal: x,
value: None,
}
}
fn value(&mut self, arg: i32) -> i32 {
match self.value {
Some(x) => x,
None => {
let v = (self.cal)(arg);
self.value = Some(v);
v
}
}
}
}
使用闭包捕获环境
直接使用函数不能捕获外界的变量
// can't capture dynamic environment in a fn item
let x = 5;
fn f(y: i32) -> i32 {
x
}
println!("{}", f(x));
使用闭包捕获外界的值
let x = 5;
let f = |num: i32| -> i32 {
x
};
println!("{}", f(x));
闭包从所在环境捕获值的方式
- FnOnce 取得所有权
- FnMut 可变借用
- Fn 不可变借用
move
关键字,强制闭包获得它使用环境值的所有权
let x = String::from("2024");
let f = move || { // move
x == String::from("2024")
};
println!("{}", x);
// value borrowed here after move
Processing a Series of Items with Iterators
迭代器模式:对一系列项执行某些任务
迭代器负责:遍历每个项,确定序列(遍历)何时完成
rust 的迭代器
懒惰的: 除非调用消费迭代器的方法,否则迭代器本身没有任何效果
let v = vec![1, 2, 3];
let v_iter = v.iter();
for x in v_iter {
println!("{}", x);
}
iterator trait
所有 迭代器都实现了 iterator trait
iterator trait 仅要求实现一个方法 next
next 每次返回迭代器中的一项,返回结果包裹在 Some, 结束返回 None
迭代器使用
- iter : 在不可变引用上创建迭代器
- into_iter : 创建的迭代器会获得所有权
- iter_mut : 迭代可变的引用
map
接受一个闭包,闭包作用于每个元素,产生一个新的迭代器
collect
消耗型适配器,把结果收集到一个集合类型中
let v = vec![1, 2, 3];
let v_iter = v.iter();
let v1: Vec<_> = v_iter.map(|x| x + 1).collect();
assert_eq!(vec![2, 3, 4], v1);
filter
接受闭包,闭包返回 bool 类型,当返回 true 时,产生的迭代器就会包含该元素
let v = vec![1, 2, 3, 5, 6];
let v_iter = v.into_iter(); // 获取所有权
let v1: Vec<_> = v_iter.filter(|x| x % 3 == 0).collect();
assert_eq!(vec![3, 6], v1);
自定义迭代器,实现 next
struct Counter {
count: u32,
}
impl Iterator for Counter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if self.count < 5 {
self.count += 1;
Some(self.count)
} else {
None
}
}
}
Comparing Performance: Loops vs. Iterators
迭代器与循环效率比较
迭代器效率更高
迭代器是 Rust 的 零成本抽象(zero-cost abstractions)之一,它意味着抽象并不会引入运行时开销