我有以下代码
pub struct PropertyDeclarationBlock {
pub declarations: Arc<Vec<(PropertyDeclaration, PropertyDeclarationImportance)>>
}
impl PropertyDeclarationBlock {
pub fn select_declarations(&self) -> Arc<Vec<PropertyDeclaration>> {
Arc::new(self.declarations.clone().map_in_place(|p| {
let (declaration, _) = p;
declaration
}))
}
}
我希望能够在PropertyDeclarationBlock上调用.select_declarations()并让它返回声明的克隆,但不是它是Arc Vec(PropertyDeclaration,PropertyDeclarationImportance)只是一个Arc Vec PropertyDeclaration,换句话说返回一个PropertyDeclaration的向量而不是前一个元组。
之前不会编译,因为我收到以下错误:
error: cannot move out of dereference of `&`-pointer
Arc::new(self.declarations.clone().map_in_place(|p| {
^~~~~~~~~~~~~~~~~~~~~~~~~
据我所知,由于该函数将self作为参数,因此它将拥有它的所有权。因为我宁愿使用burrow self函数,所以我使用&amp;。
修改
以下是实现新功能后的错误消息:
error: cannot move out of dereference of `&`-pointer
Arc::new(self.declarations.iter().map(|&(declaration, _)| declaration).collect())
^~~~~~~~~~~~~~~~~
note: attempting to move value to here (to prevent the move, use `ref declaration` or `ref mut declaration` to capture value by reference)
Arc::new(self.declarations.iter().map(|&(declaration, _)| declaration).collect())
^~~~~~~~~~~
我尝试在声明之前应用ref关键字,如错误消息所示,但它没有帮助。
答案 0 :(得分:1)
self.declarations.clone()
克隆Arc
,而我相信您打算克隆Vec
。要解析对map_in_place
的调用,编译器会自动取消引用Arc
以便能够调用Vec
上定义的方法。编译器知道如何取消引用Arc
,因为Arc
实现了Deref
。 deref
返回一个借来的指针,这就是错误的来源。要克隆Vec
,我们必须明确取消引用Arc
:(*self.declarations).clone()
。
但是,map_in_place
在这种情况下不合适,因为(PropertyDeclaration, PropertyDeclarationImportance)
的大小与PropertyDeclaration
的大小不同(除非PropertyDeclarationImportance
的大小为零,可能不是这种情况),这是每个文档所必需的。它失败并显示类似于此的消息:
task '<main>' failed at 'assertion failed: mem::size_of::<T>() == mem::size_of::<U>()', /build/rust-git/src/rust/src/libcollections/vec.rs:1805
这是一个正确的实施:
impl PropertyDeclarationBlock {
pub fn select_declarations(&self) -> Arc<Vec<PropertyDeclaration>> {
Arc::new(self.declarations.iter().map(|&(declaration, _)| declaration).collect())
}
}
在这里,我们在Vec
上使用iter
来创建向量项目的迭代器。这将返回Items
,它在不可变引用上实现Iterator
。
然后,我们使用map
懒洋洋地将(PropertyDeclaration, PropertyDeclarationImportance)
映射到PropertyDeclaration
。注意我们如何解析闭包的参数列表中的元组和引用(这也适用于fn
)而不是使用let
语句。
最后,我们使用collect
为此序列创建一个新的集合容器。 collect
的结果是通用的;它可以是任何实现FromIterator
的类型。 Vec
实现FromIterator
,编译器从方法的签名中推断出Vec
。