我正在尝试使用Rust 1.36.0和Futures 0.1建立期货向量。
Future
我的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
的{{1}},我希望它与FutureResult
兼容。
我正在使用旧版本的期货箱,因为我要参与的另一个项目正在使用0.1版本。我知道Future
的关联类型在0.3.x中是dyn Future<Item = i32, Error = ()>
。如果切换到最新版本,也许不会有这个问题,但是我想了解一下上面的情况,以便更好地了解Rust。错误消息与1.39.0相同。
答案 0 :(得分:1)
为什么下面的代码不起作用?
我认为此问题并非特定于您使用的期货版本-如果我更新您的代码以使用Future<Output = Result<i32, i32>>
,那么我得到exactly the same result。
这里的问题是,您的映射功能需要将具体的未来胁迫为特征对象。
在Rust参考中,type coercions的小节中将强制位置描述为:
需要的类型是显式的或可以通过从显式类型的传播而派生的地方(无类型推断)。
您的代码需要强制转换的上下文将需要类型推断-从所需的容器类型到map
函数的返回类型进行反向操作。这是一座太遥远的桥梁。
您可以通过显式转换为特征对象来克服它:
Box::new(futures::future::ok(132)) as Box<dyn futures::future::Future<Output = Result<i32, i32>>>
现在它将编译(playground)。
为避免隐式转换,您可以在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();
这将使隐性强制生效。
是否有一种更惯用的方式来构建{/ {1}}的列表/可重复项?
这将取决于期货的创建方式和用途。
您可以定义类型别名:
Future
这样您就可以写:
type MyDynFuture = Box<dyn futures::future::Future<Output = Result<i32, i32>>>;
我个人认为它更具可读性。
如果您的代码库中有很多地方需要 管理期货的集合,您可能想使用一个函数 而不是关闭以进一步减少样板。
如果该集合将包含有限的将来类型集合,则可能是 定义包含它们并收集的枚举更有效 枚举在容器中的实例-这样可以避免运行时 分派和堆分配。
如果从某个迭代器生成期货,则
集合将传递给join_all
或其他类似的对象
方法,这样您就可以等待它们全部完成,然后就不需要了
完全收集它们-例如:
let mapped: Vec<MyDynFuture> = (0..10)
.map(|_| -> MyDynFuture {
Box::new(futures::future::ok(132))
})
.collect();
注意:我也对Rust缺乏经验,可能还有其他我不知道的最佳实践。