如何在使用返回Result类型的函数时,结合Stream::map方法?

5

我有以下一段代码(请参见playground):

use futures::{stream, Future, Stream}; // 0.1.25
use std::num::ParseIntError;

fn into_many(i: i32) -> impl Stream<Item = i32, Error = ParseIntError> {
    stream::iter_ok(0..i)
}

fn convert_to_string(number: i32) -> Result<String, ParseIntError> {
    Ok(number.to_string())
}

fn main() {
    println!("start:");
    let vec = into_many(10)
        .map(|number| convert_to_string(number))
        .collect()
        .wait()
        .unwrap();

    println!("vec={:#?}", vec);

    println!("finish:");
}

它输出以下内容(即 Vec<Result<i32, ParseIntError>>):
start:
vec=[
    Ok(
        "0"
    ),
    Ok(
        "1"
    ),
    Ok(
        "2"
    ), ...

有没有办法让它输出一个Vec<i32>,如果发生任何错误,立即停止执行并从函数中返回(例如,像这个例子)?

注意:即使对于这个特定的示例没有意义,我也想使用use futures::Stream; // 0.1.25


你可以链接两个解决你问题的问题。 - Stargateur
@Stargateur实际上,它们不会,因为我没有实现into_iter()就无法使用它。 - James Larkin
2
你已经找到了错误的来源吗(String未实现特质Try)?快速浏览一下,看起来你需要停止在map函数内使用?,并查看collect是否可为你实现此功能(链接的文档中有一个类似于你所需的示例)。你不能只是复制粘贴其他解决方案;你需要理解你正在处理的类型并开发出适合自己的解决方案。 - user3089519
@swalladge 这正是我尝试过的,但最终我仍然得到了 Vec<Result<>>。我认为 collect() 可以用于 Iterator,但无法用于 Stream,而且我也不能使用 into_iter() - James Larkin
如果我移除 ?,则会收到以下消息:= 注意:期望类型为 `std::vec::Vec<i64>`,但发现类型为 `std::vec::Vec<std::result::Result<i64, errors::CustomError>> - James Larkin
@Stargateur请再看一下,我已经在playground上更新了问题的代码片段。 - James Larkin
3个回答

2
以下代码(playground link)是对您在问题中提出的当前代码的修改,可以得到您想要的结果:
use futures::{stream, Future, Stream}; // 0.1.25
use std::num::ParseIntError;

fn into_many(i: i32) -> impl Stream<Item = i32, Error = ParseIntError> {
    stream::iter_ok(0..i)
}

fn convert_to_string(number: i32) -> Result<String, ParseIntError> {
    Ok(number.to_string())
}

fn main() {
    println!("start:");
    let vec: Result<Vec<String>, ParseIntError> = into_many(10)
        .map(|number| convert_to_string(number))
        .collect()
        .wait()
        .unwrap()
        .into_iter()
        .collect();

    println!("vec={:#?}", vec);

    println!("finish:");
}

由于您的当前代码返回了一个`Vec`,我们可以将其转换为迭代器,并将其收集到您想要的类型中。需要类型注释,以便`collect`知道要将迭代器收集到什么类型中。
请注意,`Iterator`特质上的`collect`方法不应与`Stream`上的`collect`方法混淆。
最后,虽然这样做可以工作,但可能不完全符合您的要求,因为它仍然等待从流中收集所有结果到一个向量中,然后再使用`collect`将其转换为所需类型。我没有未来的经验,因此不确定这有多大可能(它可能是可能的,但可能需要一个不太整洁的函数式编程风格的解决方案)。

0

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接