gpt4 book ai didi

rust - 函数返回一个闭包,闭包返回一个使用环境变量的闭包

转载 作者:行者123 更新时间:2023-11-29 08:35:13 27 4
gpt4 key购买 nike

functionA返回 closureA ,那closureA返回 closureB , closureB使用 functionA 中的变量的周边环境。

fn main () {
type Closure1 = Box<Fn() -> ()>;
type Closure2 = Box<Fn() -> Closure1>;

fn closure_container() -> Closure2 {
let mut a: Vec<usize> = Vec::new();
let closure2: Closure2 = Box::new(move || {
let closure1 = || {
println!("{}", a)
};
Box::new(closure1)
});

closure2
}
}
error[E0507]: cannot move out of captured outer variable in an `Fn` closure
--> src/main.rs:9:27
|
6 | let mut a: Vec<usize> = Vec::new();
| ----- captured outer variable
...
9 | let closure1 = move || {
| ^^^^^^^ cannot move out of captured outer variable in an `Fn` closure

编译 let mut a = 100; , 但是let mut a: Vec<usize> = Vec::new();会报错!我不知道如何修复它。

最佳答案

您已经(正确地)对第一个闭包(第 7 行)使用了 move,但您还需要为第二个闭包(第 8 行)添加它:

let closure2: Closure2 = Box::new(move || {
let closure1 = move || { // <-- Add "move" on this line
println!("{}", a)
};
Box::new(closure1)
});

playground

如果 a 具有 Copy 类型,这将使​​其工作,但它会导致错误 cannot move out of captured outer variable in an 'Fn' closurea 不是 Copy 时(例如,如果 aVec)。问题是由于您将 closure2 定义为 Fn,这意味着您告诉编译器您可能想要多次调用它。然而,第一次调用 closure2 会将 a 移动到返回的 closure1 中,因此 a 将不可用下一次可能调用 closure2

长话短说:您需要将closure2 定义为FnOnce 以告诉编译器您不能多次调用它,否则您需要移动一个克隆将 a 放入 closure1 以便 closure2 将保留其副本。

方案一:FnOnce

type Closure1 = Box<Fn() -> ()>;
type Closure2 = Box<FnOnce() -> Closure1>;

fn closure_container() -> Closure2 {
let a: Vec<usize> = Vec::new();
let closure2: Closure2 = Box::new(move || {
let closure1 = move || {
println!("{:?}", a)
};
Box::new(closure1)
});

closure2
}

playground

但是请注意,虽然您可以通过这种方式创建 Closure2,但在当前稳定的 Rust 中调用它是不可能的。如果你愿意每晚使用,如果你用 FnBox 替换 FnOnce 它应该可以工作,但我遇到了另一个错误( playground )。目前,您需要使用解决方案 2 并克隆 a。如果您想避免克隆整个向量的成本,您可以使用 wrap it in an Rc and clone that ( playground )。

解决方案 2:克隆

type Closure1 = Box<Fn() -> ()>;
type Closure2 = Box<Fn() -> Closure1>;

fn closure_container() -> Closure2 {
let a: Vec<usize> = Vec::new();
let closure2: Closure2 = Box::new(move || {
let b = a.clone();
let closure1 = move || {
println!("{:?}", b)
};
Box::new(closure1)
});

closure2
}

playground

关于rust - 函数返回一个闭包,闭包返回一个使用环境变量的闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52584251/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com