gpt4 book ai didi

asynchronous - 如何在Rust中编写两个异步函数

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

我试图写一个由两个异步函数组成的高阶函数。
我基本上是在寻找异步版本this

fn compose<A, B, C, G, F>(f: F, g: G) -> impl Fn(A) -> C
where
F: Fn(A) -> B,
G: Fn(B) -> C,
{
move |x| g(f(x))
}
到目前为止,这是我的尝试。
fn compose_future<A, B, C, G, F>(f: F, g: G) -> (impl Fn(A) -> impl Future<C>)
where
F: Fn(A) -> impl Future<B>,
G: Fn(B) -> impl Future<C>,
{
move |x| async { g(f(x).await).await }
}
我得到以下错误
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
--> src\channel.rs:13:17
|
13 | F: Fn(A) -> impl Future<B>,
| ^^^^^^^^^^^^^^

有可能做到这一点吗?

最佳答案

我不确定是否可以使用impl Trait -s做到这一点。我可以提出的一个解决方案是不使用async-await功能的老式的将来类型用法。 TLDR:full playground。 Async-await使用内部生成状态机的生成器,因此我们需要手动定义它:

enum State<In, F, FutOutF, G, FutOutG> {
Initial(In, F, G), // Out composed type created
FirstAwait(FutOutF, G), // Composed type waits for the first future
SecondAwait(FutOutG), // and for the second
// here can be a `Completed` state, but it simpler
// to handle it with `Option<..>` in our future itself
}
然后定义一个组合类型本身:
struct Compose<In, Out, F, FutOutF, G, FutOutG> {
state: Option<State<In, F, FutOutF, G, FutOutG>>,
_t: PhantomData<Out>,
}

// And "entry-point" would be something like that:
fn compose_fut<In, Out, F, FutOutF, G, FutOutG>(
i: In,
f: F,
g: G,
) -> Compose<In, Out, F, FutOutF, G, FutOutG> {
Compose {
state: Some(State::Initial(i, f, g)),
_t: PhantomData,
}
}
然后是最复杂的部分- impl Future本身,这里是没有实现的基本impl声明:
impl<In, Mid, Out, F, FutOutF, G, FutOutG> Future for Compose<In, Out, F, FutOutF, G, FutOutG>
where
FutOutF: Future<Output = Mid>,
F: FnOnce(In) -> FutOutF,
FutOutG: Future<Output = Out>,
G: FnOnce(Mid) -> FutOutG,
{
type Output = Out;

fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
// here comes the magic
}
}
转换的值如下: In -> Mid -> Out,其中 FG是我们的组合函数,它们的输出分别是 FutOutFFutOutG。最后是 Future::poll实现:
let this = unsafe { self.get_unchecked_mut() };

let state = this.state.take();

match state {
None => Poll::Pending, // invalid state
Some(State::Initial(i, f, g)) => {
let fut = f(i);
this.state = Some(State::FirstAwait(fut, g));
cx.waker().wake_by_ref();
Poll::Pending
}
Some(State::FirstAwait(mut fut, g)) => {
let val = match unsafe { Pin::new_unchecked(&mut fut) }.poll(cx) {
Poll::Ready(v) => v,
Poll::Pending => {
this.state = Some(State::FirstAwait(fut, g));
return Poll::Pending;
}
};
let fut = g(val);
this.state = Some(State::SecondAwait(fut));
cx.waker().wake_by_ref();
Poll::Pending
}
Some(State::SecondAwait(mut fut)) => {
match unsafe { Pin::new_unchecked(&mut fut) }.poll(cx) {
Poll::Ready(v) => Poll::Ready(v),
Poll::Pending => {
this.state = Some(State::SecondAwait(fut));
Poll::Pending
}
}
}
}
我避免使用任何库来使其“普通”,通常,不安全的零件使用 pin-projectfutures::pin_mut处理。状态管理相当复杂,因此我建议重新检查实现情况,可能会出现错误。

关于asynchronous - 如何在Rust中编写两个异步函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62724721/

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