gpt4 book ai didi

rust - 为什么通过移动捕获Arc会使我的关闭 FnOnce 而不是 Fn

转载 作者:行者123 更新时间:2023-12-03 09:27:20 25 4
gpt4 key购买 nike

在下面的示例中,我使用 Arc 从请求处理程序引用服务器状态,但编译器将闭包设为 FnOnce .感觉就像我在做正确的事情,因为每个闭包都拥有对状态的强引用。为什么这不起作用?有什么选择可以使它工作?其他问题,如 Share Arc between closures表明类似这样的工作,但我正在制作如图所示的每个闭包克隆,但仍然出现错误。

#![feature(async_closure)]

#[derive(Default, Debug)]
struct State {}

impl State {
pub async fn exists(&self, key: &str) -> bool {
true
}

pub async fn update(&self, key: &str) {}
}

#[tokio::main]
async fn main() {
use warp::Filter;
use std::sync::Arc;

let state: Arc<State> = Arc::default();

let api = warp::post()
.and(warp::path("/api"))
.and(warp::path::param::<String>().and_then({
let state = Arc::clone(&state);
async move |p: String| {
let x = state.exists(&p);
if x.await {
Ok(p)
} else {
Err(warp::reject::not_found())
}
}
}))
.and_then({
let state = Arc::clone(&state);
async move |id: String| {
state.update(&id).await;
Result::<String, warp::Rejection>::Ok("".to_owned())
}
});

warp::serve(api).run(([127, 0, 0, 1], 0)).await;
}

error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
--> src/main.rs:25:13
|
23 | .and(warp::path::param::<String>().and_then({
| -------- the requirement to implement `Fn` derives from here
24 | let state = Arc::clone(&state);
25 | async move |p: String| {
| _____________^^^^^^^^^^^^^^^^^^^^^^_-
| | |
| | this closure implements `FnOnce`, not `Fn`
26 | | let x = state.exists(&p);
27 | | if x.await {
28 | | Ok(p)
... |
31 | | }
32 | | }
| |_____________- closure is `FnOnce` because it moves the variable `state` out of its environment

最佳答案

嗯,异步闭包不稳定,所以这可能是一个错误。我认为当异步块捕获 Arc 时它消耗它,所以闭包实际上只能被调用一次。我的意思是,异步闭包是某种生成器:每次调用它时,它都会构造一个 future ,而这个 future 会保留捕获的值。

作为一种解决方法,您可以编写如下内容:

let state = Arc::clone(&state);
move |p: String| {
let state = Arc::clone(&state);
async move {
let x = state.exists(&p);
//...
}
}

在闭包内但在 async 之前做另一个克隆块确保您可以根据需要多次调用闭包。

我认为实际上 Warp::Filter应该接受 FnOnce开始,但我不知道 warp足以确定。

关于rust - 为什么通过移动捕获Arc会使我的关闭 FnOnce 而不是 Fn,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62383234/

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