关闭和功能如何传递一个论点?

ena*_*naJ 2 closures rust

我正在阅读Rust书中的闭包示例.对于以下示例代码:

fn factory() -> Box<Fn(i32) -> i32> {
    let num = 5;

    Box::new(move |x| x + num)
}

fn main() {
    let f = factory();
    let answer = f(1);
    assert_eq!(6, answer);
}
Run Code Online (Sandbox Code Playgroud)

工厂是一个带0参数的函数,但绑定factory()f,为什么可以f(1)将1的参数传递给工厂?

DK.*_*DK. 5

它没有.关于闭包的工作方式,您可能有错误的心智模型.

闭包只是一个函数的语法简写,具有一个额外的初始参数,可以从定义环境中捕获值.我们可以将您的示例重写为逻辑上等效的内容:

fn factory() -> Box<Closure> {
    let num = 5;

    Box::new(Closure { num: num })
}

struct Closure {
    num: i32,
}

impl Closure {
    pub fn invoke(&self, x: i32) -> i32 {
        x + self.num
    }
}

fn main() {
    let f = factory();
    let answer = f.invoke(1);
    assert_eq!(6, answer);
}
Run Code Online (Sandbox Code Playgroud)

注意在构造"闭包"时如何num捕获 "闭包".闭包的主体访问这个通道self(这是真正的封闭魔术).

与您的原始代码之间的唯一区别是:

  1. Closure类型存在,但匿名的.也就是说,您不能直接命名类型,因此您必须Fn(i32) -> i32在返回类型中使用.

  2. 由于上述原因,我们返回一个盒装混凝土类型,而不是盒装特征对象.就如何使用"封闭"而言,这对我们来说并不重要.我们无法返回的原因Box<Fn(i32) -> i32>是因为......

  3. 我们没有实施Fn.这还不能在稳定的代码中完成.如果可以,它几乎与invoke方法相同.

  4. 我们在factory函数之外定义"闭包"的主体.然而,这仅仅是一个语法差别:一个封闭的身体不再是你的执行"部分" factory比身体invoke是执行的"一部分" 这个 factory.

所以希望你可以看到,执行并没有返回factory功能:它进入不同的功能,只是碰巧被定义之内factory,为方便起见.