Вы (по праву) использовали move
для первого закрытия (строка 7), но вам также необходимо добавить его для второго закрытия (строка 8):
let closure2: Closure2 = Box::new(move || {
let closure1 = move || { // <-- Add "move" on this line
println!("{}", a)
};
Box::new(closure1)
});
детская площадка
Это работает, если a
имеет тип Copy
, но вызывает ошибку cannot move out of captured outer variable in an 'Fn' closure
, когда a
не Copy
(например, если a
является Vec
).Проблема связана с тем, что вы определяете closure2
как Fn
, что означает, что вы сообщаете компилятору, что вы можете вызывать его более одного раза.Однако в первый раз, когда вы позвоните closure2
, вы переведете a
в возвращенное значение closure1
, поэтому a
не будет доступно для возможного следующего вызова на closure2
.
Короче говоря:вам нужно определить closure2
как FnOnce
, чтобы сообщить компилятору, что вы не можете вызвать его более одного раза, или вам нужно переместить клон a
в 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
}
детская площадка
Обратите внимание, что хотя вы можете создать a Closure2
таким образом, невозможно вызвать в текущем стабильном Rust.Если вы хотите использовать ночной режим, он должен работать, если вы замените FnOnce
на FnBox
, но я получаю еще одну ошибку с этим ( детская площадка ).Пока вам нужно будет использовать решение 2 и клон 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
}
детская площадка