gpt4 book ai didi

rust - 如何从 Rust 中的 Fn 闭包内部更改变量?

转载 作者:行者123 更新时间:2023-11-29 07:44:20 26 4
gpt4 key购买 nike

我有以下代码(playground):

struct A {
pub vec: Vec<u64>,
}

impl A {
fn perform_for_all<F: Fn(&mut u64)>(&mut self, f: F) {
for mut i in &mut self.vec {
f(i);
}
}
}
fn main() {
let mut a = A {
vec: vec![1, 3, 44, 2, 4, 5, 6],
};

let mut done = false;

a.perform_for_all(|v| {
println!("value: {:?}", v);
done = true;
});

if !done {
a.perform_for_all(|v| {
println!("value {:?}", v);
});
}
}

出现以下错误:

error[E0594]: cannot assign to `done`, as it is a captured variable in a `Fn` closure
--> src/main.rs:21:9
|
21 | done = true;
| ^^^^^^^^^^^ cannot assign
|
help: consider changing this to accept closures that implement `FnMut`
--> src/main.rs:19:23
|
19 | a.perform_for_all(|v| {
| _______________________^
20 | | println!("value: {:?}", v);
21 | | done = true;
22 | | });
| |_____^

我有一个加载对象列表和一个数据库中的对象列表。我需要一个函数,它接受一个闭包并在加载的对象上执行它,如果列表中没有对象,则在数据库中的对象列表上执行它。

这个函数看起来像:

pub fn perform_for_match_with_mark<F>(&mut self, mark: MatchMark, f: F)
where
F: Fn(&mut GameMatch),
{
self.perform_for_all_matches(
|m| {
// runtime list
if let Game::Match(ref mut gm) = *m {
if gm.match_stamp().mark == mark {
f(gm);
}
}
},
None,
);
// if we have called `f` above - don't execute lines below.
let tx = self.match_tx.clone();
GamesDatabase::perform_for_match_with_mark(mark, |ms| {
// database
self.perform_for_all_matches(
|m| {
if let Game::Match(ref gm) = *m {
if gm.match_stamp().id == ms.id {
f(&mut GameMatch::new_with_match_stamp(
tx.clone(),
ms.clone(),
gm.needs_server_set,
gm.server_id,
))
}
}
},
None,
);
});
}

只有当我们无法在运行时列表中找到它们时,我们才必须对数据库中的对象进行操作。这就是为什么我决定创建一个变量来表示“我们已经在列表中找到了这些对象,不用管数据库”。

最佳答案

更改您的perform_for_all 函数以使用FnMut而不是 Fn :

fn perform_for_all<F>(&mut self, mut f: F)
where
F: FnMut(&mut u64),
{
for mut i in &mut self.vec {
f(&mut i);
}
}

As Peter said , 有一些编译器魔法在发生。

Fn::call 的签名是:

extern "rust-call" fn call(&self, args: Args) -> Self::Output

这需要对 self 的不可变引用,这就是为什么您不能修改任何捕获的变量的原因。

FnMut::call_mut 的签名让你改变变量,因为它需要 &mut self:

extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output

通过将闭包从 Fn 更改为 FnMut,您允许它修改其捕获的变量,前提是您传递给它的引用是可变的。

关于rust - 如何从 Rust 中的 Fn 闭包内部更改变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41239266/

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