【问题标题】:Recursively visiting enums in a Hashmap递归访问 Hashmap 中的枚举
【发布时间】:2016-07-15 17:50:30
【问题描述】:

我用一个枚举、两个结构和一个 BTreeMap 建模了一个类似文件系统的结构,如下所示(简化):

pub enum Item {
    Dir(Dir),
    File(File),
}

struct Dir {
    ...
    children: BTreeMap<String, Item>,
}

struct File {
    ...
}

现在我需要遍历一个目录并对每个文件进行一些操作。我试过这个:

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) =>

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

非常感谢任何帮助。

【问题讨论】:

    标签: loops enums hashmap iteration rust


    【解决方案1】:

    您的代码存在几个问题。这是一个带有编号更改的工作版本:

    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上已经有someanswers解释了为什么会这样。我们希望在不消耗的情况下进行迭代,但能够改变值。
    2. 由于 (1.) 函数还需要有一个对Dir可变 引用
    3. child&amp;mut Item 类型的可变引用(因为这是迭代器产生的)。匹配块中的模式(例如Item::File(/* ... */))的类型为Item。这是类型不匹配(您的第二个编译器错误)。我们可以通过使用* 取消引用child 来解决这个问题。
    4. 所以match 块与Item 匹配,但我们实际上并不拥有该项目并且无法移出它。为了防止移动,我们添加了ref 关键字。现在fd 是引用,我们避免了移动。

    【讨论】:

    • 谢谢!您在 1. 中的解释是我尝试使用 .iter() 的原因(因为它返回引用)。我发现该手册在整个 &、&mut、ref 和 * 以及您可以使用它们的地方都非常混乱。很清楚它们在函数参数和调用参数中使用时的作用,但我永远不会尝试在 for...in 或 * 后使用 &mut ...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    • 1970-01-01
    • 1970-01-01
    • 2021-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多