rust - 函数返回一个闭包,该闭包返回一个使用环境变量的闭包
问题描述
functionA
返回closureA
,并且closureA
返回 a 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();
会报错!我不知道如何解决它。
解决方案
您(正确地)用于move
第一个闭包(第 7 行),但您还需要为第二个闭包(第 8 行)添加它:
let closure2: Closure2 = Box::new(move || {
let closure1 = move || { // <-- Add "move" on this line
println!("{}", a)
};
Box::new(closure1)
});
a
如果有类型,这使得它可以工作,但是当没有Copy
类型时它会导致错误(例如,如果是 a )。问题是由于您将其定义为,这意味着您告诉编译器您可能要多次调用它。但是,您第一次调用将移至返回的,因此将无法用于可能的下一次调用.cannot move out of captured outer variable in an 'Fn' closure
a
Copy
a
Vec
closure2
Fn
closure2
a
closure1
a
closure2
长话短说:您需要定义closure2
asFnOnce
告诉编译器您不能多次调用它,或者您需要将克隆移至 ina
以便closure1
保留closure2
其副本。
解决方案1: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
}
但是请注意,尽管您可以通过这种方式创建一个,但在当前稳定的 Rust 中Closure2
是不可能调用它的。如果您愿意每晚使用,如果您替换为 ,它应该可以工作FnOnce
,FnBox
但我遇到了另一个错误(操场)。目前,您将需要使用解决方案 2 和 clone a
。如果你想避免克隆整个向量的成本,你可以将它包装在一个Rc
并克隆它(操场)。
解决方案 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
}
推荐阅读
- java - Spring 应用程序启动,但我总是看到“Whitelabel 错误页面”
- wordpress - @@History/@@scroll|# Cookie
- sybase - 在整个 Sybase 数据库中搜索一串数据
- types - 无法返回需要强制转换的类型 (F#)
- angular - 角度 - 可以在不同组件中使用相同的属性名称吗?
- azure - 使用本地 DNS 服务器的 Service Fabric VM 无法解析
- paypal - PayPal TLS 1.2 和 HTTP/1.1 升级问题
- python - Tensorflow:tf.train.Feature 错误“预期之一:字节”
- niftynet - 广义骰子损失:在 keras 中实现时无梯度
- android - 在 android 上更新 PWA 图标