【问题标题】:Conditionally chaining a Rust future based on initial future result?根据初始未来结果有条件地链接 Rust 未来?
【发布时间】:2018-11-02 21:24:10
【问题描述】:

如果我有一些要链接在一起的期货,我怎样才能使第二个链接的未来以第一个未来的结果为条件?

举一个人为的例子,我有类似的东西:

extern crate futures;
extern crate tokio_core;

use futures::{future, Future};
use tokio_core::reactor::Core;

fn add_one(x: i64) -> impl Future<Item = i64, Error = ()> {
    future::ok(x).map(|x| x + 1)
}

fn double(x: i64) -> impl Future<Item = i64, Error = ()> {
    future::ok(x).map(|x| x * 2)
}

fn add_one_then_double(x: i64) -> impl Future<Item = i64, Error = ()> {
    future::ok(x).and_then(add_one).and_then(double)
}

fn main() {
    let mut reactor = Core::new().unwrap();
    println!("{:?}", reactor.run(add_one_then_double(10)).unwrap());
}

然后我怎样才能将add_one_then_double 未来更改为以add_one 未来的结果为条件,例如:

fn add_one_then_double_if_positive(x: i64) -> impl Future<Item = i64, Error = ()> {
    future::ok(x).and_then(add_one).map(|v| {
        if v >= 0 {
            // chain the `double` future
        } else {
            // return `v` as the result
        }
    })
}

【问题讨论】:

  • 我相信How do I conditionally return different types of futures?的答案已经回答了您的问题。如果您不同意,请edit您的问题解释差异。否则,我们可以将此问题标记为已回答。
  • @Shepmaster 其他问题只是答案的一部分。这里的重点是如何有条件地在一个分支中链接未来,而不是在另一个分支中。因此,作为答案的第二部分,我们需要使用future::ok() 将值不变地传递。
  • @SvenMarnach 但 OP 已经知道如何使用 future::ok,代码中提供的它的使用证明了这一点。
  • @Shepmaster 问题的其余部分表明并非如此。
  • @Shepmaster 我很高兴把它交给你。您链接的问题让我更接近答案(尽管我没有通过搜索找到它,因为我只是在寻找有条件链接的方法,而不是涉及新未来的解决方案)。斯文的回答也很有帮助,而且更接近我最终可能得到的答案。实际问题比我想象的要复杂,但我会先看看我是否可以使用Either 解决任何问题。

标签: rust rust-tokio


【解决方案1】:

如果你想链接另一个未来,你需要使用and_then()未来组合器,而不是map()。这个组合器期望另一个未来作为返回值,所以你的if 语句的两个 分支需要产生一个未来。在第一个分支中,您想要链接double(v),这已经是一个未来。在第二个分支中,您希望传递不变的值,因此您需要将其转换为使用future::ok() 立即解析为v 的未来。由于double(v)future::ok(v) 有不同的类型,你需要要么使用future::Either,要么将future 装箱。这是一种选择:

fn add_one_then_double(x: i64) -> impl Future<Item=i64, Error=()> {
    future::ok(x)
        .and_then(add_one)
        .and_then(|v| {
            if v >= 0 {
                future::Either::A(double(v))
            } else {
                future::Either::B(future::ok(v))
            }
        })
}

Playground

【讨论】:

    猜你喜欢
    • 2016-04-02
    • 2019-09-23
    • 1970-01-01
    • 2022-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多