我使用枚举,两个结构和一个BTreeMap建模了一个类似文件系统的结构,就像这样(简化):
pub enum Item {
Dir(Dir),
File(File),
}
struct Dir {
...
children: BTreeMap<String, Item>,
}
struct File {
...
}
现在我需要遍历Dir并对每个文件执行一些操作。我试过这个:
fn process(index: &Dir) {
for (_, child) in index.children {
match child {
Item::File(mut f) => {
let xyz = ...;
f.do_something(xyz);
},
Item::Dir(d) => {
process(&d);
}
}
}
}
但我明白了:
error: cannot move out of borrowed content [E0507]
for (_, child) in index.children {
^~~~~
我也试过
for (_, child) in index.children.iter() {
然后我得到了
error: mismatched types:
expected `&Item`,
found `Item`
(expected &-ptr,
found enum `Item`) [E0308]
src/... Item::File(mut a) => {
^~~~~~~~~~~~~~~~~
我尝试了几种组合:
for (_, child) in &(index.children)
for (_, child) in index.children.iter().as_ref()
match(child) { Item::File(&mut f) =>
match(child) { Item::File(ref mut f) =>
等等,但无法找到让借款检查员满意的方法。
非常感谢任何帮助。
答案 0 :(得分:2)
您的代码存在一些问题。这是一个带有编号更改的工作版本:
fn process(index: &mut Dir) {
// ^^^-- #2
for (_, child) in &mut index.children {
// ^^^-- #1
match *child {
//^-- #3
Item::File(ref mut f) => {
// ^^^-- #4
f.do_something();
},
Item::Dir(ref mut d) => {
// ^^^-- #4
process(d);
}
}
}
}
for /* ... */ in index.children
尝试将children
移动到迭代中。 SO上已经some answers解释了为什么会出现这种情况。我们希望迭代而不消耗,但能够改变值。Dir
child
是类型&mut Item
的可变引用(因为这是迭代器产生的)。匹配块中的模式(例如Item::File(/* ... */)
)具有类型Item
。这是类型不匹配(您的第二个编译器错误)。我们可以通过child
取消引用*
来解决此问题。match
块在Item
上匹配,但我们实际上并不拥有该项,也无法移出它。为防止迁移,我们添加了ref
关键字。现在f
和d
是引用,我们避免了移动。