如何将 Stream::map 与 returns 结果的函数一起使用?
How can I use Stream::map with a function that returns Result?
我得到了以下代码(参见 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>
并且如果发生任何错误而不是立即停止执行并从函数中 return (例如 this example)?
注意:我确实想使用 use futures::Stream; // 0.1.25
,即使它对这个特定示例没有意义。
以下代码 (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转换向量。我没有期货方面的经验,所以不确定这有多大可能(它可能是但可能需要一个不太简洁的函数式编程风格解决方案)。
map
with a function that returns Result
不要这样做,那不是你应该使用 map
的时候。相反,使用 and_then
:
let vec = into_many(10)
.and_then(|number| convert_to_string(number))
.collect()
.wait()
.unwrap();
在深入研究 futures 之前,您应该练习更简单的 Rust 概念,例如 Option
、Result
和迭代器。很多概念都转移过来了。
另请参阅:
我得到了以下代码(参见 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>
并且如果发生任何错误而不是立即停止执行并从函数中 return (例如 this example)?
注意:我确实想使用 use futures::Stream; // 0.1.25
,即使它对这个特定示例没有意义。
以下代码 (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转换向量。我没有期货方面的经验,所以不确定这有多大可能(它可能是但可能需要一个不太简洁的函数式编程风格解决方案)。
map
with a function that returnsResult
不要这样做,那不是你应该使用 map
的时候。相反,使用 and_then
:
let vec = into_many(10)
.and_then(|number| convert_to_string(number))
.collect()
.wait()
.unwrap();
在深入研究 futures 之前,您应该练习更简单的 Rust 概念,例如 Option
、Result
和迭代器。很多概念都转移过来了。
另请参阅: