Rust: Functional Language Features Iterators and Closures

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)之一,它意味着抽象并不会引入运行时开销

1 个赞