我正在阅读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的参数传递给工厂?
它没有.关于闭包的工作方式,您可能有错误的心智模型.
闭包只是一个函数的语法简写,具有一个额外的初始参数,可以从定义环境中捕获值.我们可以将您的示例重写为逻辑上等效的内容:
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(这是真正的封闭魔术).
这与您的原始代码之间的唯一区别是:
该Closure类型存在,但匿名的.也就是说,您不能直接命名类型,因此您必须Fn(i32) -> i32在返回类型中使用.
由于上述原因,我们返回一个盒装混凝土类型,而不是盒装特征对象.就如何使用"封闭"而言,这对我们来说并不重要.我们无法返回的原因Box<Fn(i32) -> i32>是因为......
我们没有实施Fn.这还不能在稳定的代码中完成.如果可以,它几乎与invoke方法相同.
我们在factory函数之外定义"闭包"的主体.然而,这仅仅是一个语法差别:一个封闭的身体不再是你的执行"部分" factory比身体invoke是执行的"一部分" 这个 factory.
所以希望你可以看到,执行并没有返回factory功能:它进入不同的功能,只是碰巧被定义之内factory,为方便起见.