如何将 futures 0.1 迭代器收集到向量中?
How do I collect a futures 0.1 iterator into a vector?
我正在尝试使用 Rust 1.36.0 和 futures 0.1 构建 futures 向量。
- 为什么下面的代码不起作用?
- 是否有更惯用的方法来构建
Future
的 list/iterable?
extern crate futures;
pub fn create_some_futures() {
let mapped: Vec<Box<dyn futures::future::Future<Item = i32, Error = ()>>> = (0..10)
.map(|_| Box::new(futures::future::ok(132)))
.collect();
}
fn main() {
create_some_futures();
}
我的Cargo.toml
:
[dependencies]
futures = "0.1"
这不编译:
error[E0277]: a collection of type `std::vec::Vec<std::boxed::Box<dyn futures::Future<Item = i32, Error = ()>>>` cannot be built from an iterator over elements of type `std::boxed::Box<futures::Failed<{integer}, _>>`
--> src/main.rs:6:10
|
6 | .collect();
| ^^^^^^^ a collection of type `std::vec::Vec<std::boxed::Box<dyn futures::Future<Item = i32, Error = ()>>>` cannot be built from `std::iter::Iterator<Item=std::boxed::Box<futures::Failed<{integer}, _>>>`
|
= help: the trait `std::iter::FromIterator<std::boxed::Box<futures::Failed<{integer}, _>>>` is not implemented for `std::vec::Vec<std::boxed::Box<dyn futures::Future<Item = i32, Error = ()>>>`
这是为什么?我怀疑将 futures::Finished<{integer}, _>
转换为 <dyn futures::Future<Item = i32, Error = ()>>
有问题,因为这样编译很好:
pub fn create_some_boxed_ints() {
let mapped: Vec<Box<i32>> = (0..10).map(|_| Box::new(132)).collect();
}
我不确定是什么问题。函数 future::ok
returns FutureResult
实现了 Future
,我希望它与 dyn Future<Item = i32, Error = ()>
.
兼容
我正在玩这个旧版本的 futures crate,因为我想贡献的另一个项目正在使用 0.1 版本。我知道 Future
的关联类型是 0.3.x 中的 Output
。如果我切换到更新的版本,也许我不会有这个问题,但我想了解上面的案例以更好地理解 Rust。错误消息在 1.39.0 上是相同的。
为什么下面的代码不起作用?
我不认为这个问题特定于您使用的期货版本 - 如果我更新您的代码以使用 Future<Output = Result<i32, i32>>
然后我得到 exactly the same result.
这里的问题是您的映射函数需要将具体的未来强制转换为特征对象。
在 Rust 参考中,在 type coercions 部分中,它描述了强制转换站点:
places where the desired type is explicit or can be derived by propagation from explicit types (without type inference).
您的代码需要强制转换的上下文将需要类型推断 - 从所需的容器类型通过 map
函数的 return 类型向后工作。桥太远了。
您可以通过显式转换为特征对象来克服它:
Box::new(futures::future::ok(132)) as Box<dyn futures::future::Future<Output = Result<i32, i32>>>
现在它将编译 (playground)。
为避免隐式转换,您可以将 return 类型添加到 map
闭包中:
let mapped: Vec<Box<dyn futures::future::Future<Output = Result<i32, i32>>>> = (0..10)
.map(|_| -> Box<dyn futures::future::Future<Output = Result<i32, i32>>> {
Box::new(futures::future::ok(132))
})
.collect();
这将允许隐式强制生效。
是否有更惯用的方法来构建 Future
的 list/iterable?
这将取决于期货的创建方式以及它们的用途。
你可以定义一个类型别名:
type MyDynFuture = Box<dyn futures::future::Future<Output = Result<i32, i32>>>;
这样你就可以写:
let mapped: Vec<MyDynFuture> = (0..10)
.map(|_| -> MyDynFuture {
Box::new(futures::future::ok(132))
})
.collect();
我个人觉得更易读。
如果你的代码库中有很多地方你需要
管理期货的集合,你可能想使用一个函数
而不是关闭以进一步减少样板文件。
如果集合将包含一组有限的未来类型,那么它可能是
更有效地定义一个包含它们的枚举并收集
容器中此枚举的实例 - 这将避免运行时
分派和堆分配。
如果期货是从某个迭代器生成的,并且
集合将被传递给 join_all
或类似的
方法,这样你就可以等待它们全部完成,那么你就不需要
收集它们 - 例如:
let i = (0..10)
.map(|n| -> futures::future::Ready<Result<i32,i32>> {
futures::future::ok(n)
});
join_all(i)
警告:我在 Rust 方面也很缺乏经验,可能还有其他我不知道的最佳实践。
我正在尝试使用 Rust 1.36.0 和 futures 0.1 构建 futures 向量。
- 为什么下面的代码不起作用?
- 是否有更惯用的方法来构建
Future
的 list/iterable?
extern crate futures;
pub fn create_some_futures() {
let mapped: Vec<Box<dyn futures::future::Future<Item = i32, Error = ()>>> = (0..10)
.map(|_| Box::new(futures::future::ok(132)))
.collect();
}
fn main() {
create_some_futures();
}
我的Cargo.toml
:
[dependencies]
futures = "0.1"
这不编译:
error[E0277]: a collection of type `std::vec::Vec<std::boxed::Box<dyn futures::Future<Item = i32, Error = ()>>>` cannot be built from an iterator over elements of type `std::boxed::Box<futures::Failed<{integer}, _>>`
--> src/main.rs:6:10
|
6 | .collect();
| ^^^^^^^ a collection of type `std::vec::Vec<std::boxed::Box<dyn futures::Future<Item = i32, Error = ()>>>` cannot be built from `std::iter::Iterator<Item=std::boxed::Box<futures::Failed<{integer}, _>>>`
|
= help: the trait `std::iter::FromIterator<std::boxed::Box<futures::Failed<{integer}, _>>>` is not implemented for `std::vec::Vec<std::boxed::Box<dyn futures::Future<Item = i32, Error = ()>>>`
这是为什么?我怀疑将 futures::Finished<{integer}, _>
转换为 <dyn futures::Future<Item = i32, Error = ()>>
有问题,因为这样编译很好:
pub fn create_some_boxed_ints() {
let mapped: Vec<Box<i32>> = (0..10).map(|_| Box::new(132)).collect();
}
我不确定是什么问题。函数 future::ok
returns FutureResult
实现了 Future
,我希望它与 dyn Future<Item = i32, Error = ()>
.
我正在玩这个旧版本的 futures crate,因为我想贡献的另一个项目正在使用 0.1 版本。我知道 Future
的关联类型是 0.3.x 中的 Output
。如果我切换到更新的版本,也许我不会有这个问题,但我想了解上面的案例以更好地理解 Rust。错误消息在 1.39.0 上是相同的。
为什么下面的代码不起作用?
我不认为这个问题特定于您使用的期货版本 - 如果我更新您的代码以使用 Future<Output = Result<i32, i32>>
然后我得到 exactly the same result.
这里的问题是您的映射函数需要将具体的未来强制转换为特征对象。
在 Rust 参考中,在 type coercions 部分中,它描述了强制转换站点:
places where the desired type is explicit or can be derived by propagation from explicit types (without type inference).
您的代码需要强制转换的上下文将需要类型推断 - 从所需的容器类型通过 map
函数的 return 类型向后工作。桥太远了。
您可以通过显式转换为特征对象来克服它:
Box::new(futures::future::ok(132)) as Box<dyn futures::future::Future<Output = Result<i32, i32>>>
现在它将编译 (playground)。
为避免隐式转换,您可以将 return 类型添加到 map
闭包中:
let mapped: Vec<Box<dyn futures::future::Future<Output = Result<i32, i32>>>> = (0..10)
.map(|_| -> Box<dyn futures::future::Future<Output = Result<i32, i32>>> {
Box::new(futures::future::ok(132))
})
.collect();
这将允许隐式强制生效。
是否有更惯用的方法来构建 Future
的 list/iterable?
这将取决于期货的创建方式以及它们的用途。
你可以定义一个类型别名:
type MyDynFuture = Box<dyn futures::future::Future<Output = Result<i32, i32>>>;
这样你就可以写:
let mapped: Vec<MyDynFuture> = (0..10) .map(|_| -> MyDynFuture { Box::new(futures::future::ok(132)) }) .collect();
我个人觉得更易读。
如果你的代码库中有很多地方你需要 管理期货的集合,你可能想使用一个函数 而不是关闭以进一步减少样板文件。
如果集合将包含一组有限的未来类型,那么它可能是 更有效地定义一个包含它们的枚举并收集 容器中此枚举的实例 - 这将避免运行时 分派和堆分配。
如果期货是从某个迭代器生成的,并且 集合将被传递给
join_all
或类似的 方法,这样你就可以等待它们全部完成,那么你就不需要 收集它们 - 例如:let i = (0..10) .map(|n| -> futures::future::Ready<Result<i32,i32>> { futures::future::ok(n) }); join_all(i)
警告:我在 Rust 方面也很缺乏经验,可能还有其他我不知道的最佳实践。