递归访问Hashmap中的枚举

时间:2016-03-28 12:58:16

标签: loops enums hashmap iteration rust

我使用枚举,两个结构和一个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) =>

等等,但无法找到让借款检查员满意的方法。

非常感谢任何帮助。

1 个答案:

答案 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);
            }
        }
    }
}
  1. for /* ... */ in index.children尝试将children移动到迭代中。 SO上已经some answers解释了为什么会出现这种情况。我们希望迭代而不消耗,但能够改变值。
  2. 由于(1.)该函数还需要对Dir
  3. 可变引用
  4. child是类型&mut Item的可变引用(因为这是迭代器产生的)。匹配块中的模式(例如Item::File(/* ... */))具有类型Item。这是类型不匹配(您的第二个编译器错误)。我们可以通过child取消引用*来解决此问题。
  5. 因此match块在Item上匹配,但我们实际上并不拥有该项,也无法移出它。为防止迁移,我们添加了ref关键字。现在fd是引用,我们避免了移动。