带有类型问题的Future和Stream嵌套

时间:2018-11-01 23:39:47

标签: rust rust-tokio

我想使用一个返回Vec<String>的Future,在Future流中对其进行迭代,并将值赋予另一个Future,并应处理该Future的结果。完整的事情也应该是未来。

走什么路?我已经尝试了不同的方法,并且遇到了我不理解的类型问题。

为什么会有这些嵌套的将来结果类型签名?这不是最终结果吗?为什么编译器不知道类型?

error[E0631]: type mismatch in closure arguments
  --> src/lib.rs:45:18
   |
45 |                 .then(|x: Result<(), ()>| ok(()))
   |                  ^^^^ -------------------------- found signature of `fn(std::result::Result<(), ()>) -> _`
   |                  |
   |                  expected signature of `fn(std::result::Result<std::vec::Vec<tokio::prelude::future::Then<tokio::prelude::future::Then<impl tokio::prelude::Future, tokio::prelude::future::FutureResult<(), ()>, [closure@src/lib.rs:35:31: 41:26]>, tokio::prelude::future::FutureResult<(), _>, [closure@src/lib.rs:42:31: 42:57]>>, _>) -> _`

我为此设置了一个Playground

extern crate tokio;

use tokio::prelude::future::ok;
use tokio::prelude::*;

#[allow(dead_code)]
pub fn test_future<F>(f: F) -> Result<F::Item, F::Error>
where
    F: IntoFuture,
    F::Future: Send + 'static,
    F::Item: Send + 'static,
    F::Error: Send + 'static,
{
    let mut runtime = tokio::runtime::Runtime::new().expect("Unable to create a runtime");
    runtime.block_on(f.into_future())
}

#[allow(dead_code)]
fn fut(el: &String) -> impl Future<Item = String, Error = std::io::Error> {
    ok((el.to_string() + "-ok").to_string())
}

#[test]
fn reporting_future_result_test() {
    let v = vec![
        vec!["a".to_string(), "b".to_string()],
        vec!["a".to_string(), "b".to_string()],
    ];

    let f = stream::iter_ok(v.iter().cloned())
        .map(|el: Vec<String>| {
            stream::iter_ok(el.iter().cloned())
                .map(|ell: String| {
                    fut(&ell)
                        .then(|x: Result<String, std::io::Error>| {
                            match x {
                                Ok(s) => println!("{}", s),
                                Err(e) => println!("{:?}", e),
                            };
                            ok(())
                        })
                        .then(|x: Result<(), ()>| ok(()))
                })
                .collect()
                .then(|x: Result<(), ()>| ok(()))
        })
        .collect()
        .then(|x: Result<Vec<_>, std::io::Error>| ok(()));

    let r = test_future(f);

    match r {
        Ok(x) => println!("{:?}", x),
        Err(_) => println!("error"),
    }
}

1 个答案:

答案 0 :(得分:0)

extern crate tokio; // 0.1.11

use tokio::prelude::*;

// a future which returns a Vec<String>
fn makes_strings() -> impl Future<Item = Vec<String>, Error = ()> {
    future::ok(vec![])
}

fn make_new_string(el: String) -> impl Future<Item = String, Error = ()> {
    future::ok(el + "-ok")
}

fn iterate_over() -> impl Future<Item = Vec<String>, Error = ()> {
    makes_strings().and_then(|v| {
        // iterate over this
        let strings = v.into_iter();
        // give the values to another future
        let futures = strings.map(make_new_string);
        // The complete thing should be a future
        future::join_all(futures)
    })
}