Rust closure 闭包

发布时间: 更新时间: 总字数:875 阅读时间:2m 作者: IP上海 分享 网址

Rust中闭包(closures)可以用来捕获其所在环境的匿名函数。

介绍

闭包:

  • 是匿名函数
  • 可保存为变量、作为参数
  • 可在一个地方创建闭包,在另一个上下文中调用闭包来完成运算
  • 可从其定义的作用域捕获值

定义

let closure1 = | 变量1[, 变量2: 类型, ...] | -> 返回值类型 { 函数体 }

// call closure
closure1(参数1, ...);

说明:

  • 闭包不要求标注参数和返回值,由于闭包通常很小,编译器通常能推断出类型
  • 闭包的定义最终只会为参数/返回值推断出唯一的数据类型

示例

fn  add_v1   (x: i32) -> i32 { x + 1}   // 函数
let add_v2 = |x: i32| -> i32 { x + 1};  // 带类型标注和返回值
let add_v2 = |x|             { x + 1};
let add_v2 = |x|              x + 1;    // 函数体简单可以省略 {}

延迟计算

使用 struct 持有闭包及其调用结果,其中调用结果只有在需要时才执行对应的闭包,该模式叫延迟计算(lazy evaluation)记忆化(memoization)

适用场景:多次重复的耗时计算

struct 持有闭包:需指明 struct 闭包字段的类型

fn trait

  • fn trait 由标准库提供
  • 所有的闭包至少实现以下一个 trait:
    • Fn
    • FnMut
    • FnOnce

示例

缓冲器(Cacher)示例:

struct Cacher<T>
where
    T: Fn(u32) -> u32,
{
    calculation: T,
    value: Option<u32>,
}

impl<T> Cacher<T>
where
    T: Fn(u32) -> u32,
{
    fn new(calculation: T) -> Cacher<T> {
        Cacher {
            calculation,
            value: None,
        }
    }

    fn value(&mut self, arg: u32) -> u32 {
        match self.value {
            Some(v) => v,
            None => {
                let v = (self.calculation)(arg);
                self.value = Some(v);
                v
            }
        }
    }
}

// 声明
let mut x = Cacher::new(|num| {
    num
});
// 调用
x.vaue(1);

说明:

  • 适用 HashMap 存储闭包执行结果
    • key:arg 参数
    • value:执行闭包的结果
  • 实例中 u32 的参数类型和返回值,可以通过引入多个泛型替代

使用闭包捕获环境

闭包可以访问它的作用域内的变量,但普通函数不能。

fn main() {
    let x = 4;
    let eq_x = | z | z == x;
    // 函数不能获取作用域内的变量
    // fn eq_x(z: i32) -> bool {
    //     z == x
    // }
}

说明:

  • 闭包从所在环境捕获值的方式:
    • 取得所有权:FnOnce
    • 可变借用:FnMut
    • 不可变借用:Fn
  • 创建闭包时,通过闭包对环境值的使用,Rust可以推断出使用了哪个 trait:
    • 所有闭包都实现了 FnOnce
    • 没有移动捕获变量的实现了 FnMut
    • 无需可变访问捕获变量的闭包实现了 Fn

其他

  • 在参数列表前使用 move 关键字,可以强制闭包取得它所使用的环境值的所有权
    • 当将闭包传递给新线程以移动数据使其归新线程所有时,此技术最有用
let x = 1;
let eq_x = move | z | z == x;  // 此后,x 的所有权交给 z,在后边不能在使用 x
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数