可以使用以下代码片段就地修改函数参数:

let mut foo = 1;
let mut fun: Box<dyn FnMut(&mut i32) -> _> = Box::new(|f| {
    *f += 1;
});
fun(&mut foo);
assert_eq!(foo, 2);

然而,我遇到这样的情况,函数fun需要返回一个将来,一旦等待将来,它就会修改参数.基本上,我有以下情景:

let mut foo = 1;
assert_eq!(foo, 1);
let mut fun: Box<dyn FnMut(&mut i32) -> _> = Box::new(|f| {
    async move {
        *f += 1;
    }
});
fun(&mut foo).await;
assert_eq!(foo, 2);

rust playground

但这会产生编译错误:

error: lifetime may not live long enough
 --> src/main.rs:7:9
  |
6 |       let mut fun: Box<dyn FnMut(&mut i32) -> _> = Box::new(|f| {
  |                                                              -- return type of closure `impl Future<Output = ()>` contains a lifetime `'2`
  |                                                              |
  |                                                              has type `&'1 mut i32`
7 | /         async move {
8 | |             *f += 1;
9 | |         }
  | |_________^ returning this value requires that `'1` must outlive `'2`

error: could not compile `playground` due to previous error

我不确定如何在上面的代码片段中注释生命周期.我试过Box<dyn FnMut(&'static mut i32) -> _>次,但这说明foo次的生命周期 不够长.

有没有办法让这件事起作用?

推荐答案

您不能简单地更改来自(可能)另一个线程的值,而不使用某些同步原语将其打包.

相反,您可以将它打包为ArcMutex,并像多线程程序一样处理它:

use std::sync::{Arc, Mutex};

#[tokio::main]
async fn main() {
    let foo = Arc::new(Mutex::new(1));
    assert_eq!(*foo.lock().unwrap(), 1);
    let mut fun: Box<dyn FnMut(Arc<Mutex<i32>>) -> _> = Box::new(|f| {
        async move {
            let mut counter = f.lock().unwrap();
            *counter += 1;
        }
    });
    fun(Arc::clone(&foo)).await;
    assert_eq!(*foo.lock().unwrap(), 2);
}

Rust相关问答推荐

在HashMap中插入Vacant条目的可变借位问题

如何将元素添加到向量并返回对该元素的引用?

值为可变对象的不可变HashMap

亚性状上位性状上的 rust 病伴生型界限

通过解引用将值移出Box(以及它被脱糖到什么地方)?

在使用AWS SDK for Rust时,如何使用硬编码访问密钥ID和密钥凭据?

铁 rust ,我的模块介绍突然遇到了一个问题

如何实现Serde::Ser::Error的调试

考虑到Rust不允许多个可变引用,类似PyTorch的自动区分如何在Rust中工作?

装箱特性如何影响传递给它的参数的生命周期 ?(举一个非常具体的例子)

有没有一种方法可以创建一个闭包来计算Rust中具有随机系数的n次多项式?

如何执行数组文字的编译时串联?

为什么我必须使用 PhantomData?在这种情况下它在做什么?

如何在 `connect_activate()` 之外创建一个 `glib::MainContext::channel()` 并将其传入?

使用 HashMap 条目时如何避免字符串键的短暂克隆?

如何在 C++ 和 Rust 之间共享 pthread 同步原语?

Rust 跨同一文件夹中文件的可见性

覆盖类型的要求到底是什么?为什么单个元素元组满足它?

如何将 while 循环内的用户输入添加到 Rust 中的向量?

为什么 u64::trailing_zeros() 在无分支工作时生成分支程序集?