我试图迭代地浏览递归数据 struct ,以便在特定位置插入元素.就我有限的理解而言,这意味着对 struct 的根进行可变引用,然后依次替换为对其跟随者的引用:

type Link = Option<Box<Node>>;

struct Node {
    next: Link
}

struct Recursive {
    root: Link
}

impl Recursive {
    fn back(&mut self) -> &mut Link {
        let mut anchor = &mut self.root;
        while let Some(ref mut node) = *anchor {
            anchor = &mut node.next;
        }
        anchor
    }
}

(Rust playground link)

然而,这是失败的:

error[E0499]: cannot borrow `anchor.0` as mutable more than once at a time
  --> src/main.rs:14:24
   |
14 |         while let Some(ref mut node) = *anchor {
   |                        ^^^^^^^^^^^^
   |                        |
   |                        second mutable borrow occurs here
   |                        first mutable borrow occurs here
...
18 |     }
   |     - first borrow ends here

error[E0506]: cannot assign to `anchor` because it is borrowed
  --> src/main.rs:15:13
   |
14 |         while let Some(ref mut node) = *anchor {
   |                        ------------ borrow of `anchor` occurs here
15 |             anchor = &mut node.next;
   |             ^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `anchor` occurs here

error[E0499]: cannot borrow `*anchor` as mutable more than once at a time
  --> src/main.rs:17:9
   |
14 |         while let Some(ref mut node) = *anchor {
   |                        ------------ first mutable borrow occurs here
...
17 |         anchor
   |         ^^^^^^ second mutable borrow occurs here
18 |     }
   |     - first borrow ends here

这是有道理的,因为anchornode都指的是同一个 struct ,但实际上,在分解它之后,我不再关心anchor.

如何使用安全防 rust 剂正确实施back()

推荐答案

有可能...但我希望我有一个更优雅的解决方案.

诀窍是不要向anchor借钱,因此要在两个蓄能器之间切换:

  • 一个保存当前 node 的引用
  • 另一个 node 被分配到下一个 node 的引用

这让我想到:

impl Recursive {
    fn back(&mut self) -> &mut Link {
        let mut anchor = &mut self.root;

        loop {
            let tmp = anchor;
            if let Some(ref mut node) = *tmp {
                anchor = &mut node.next;
            } else {
                anchor = tmp;
                break;
            }
        }

        anchor
    }
}

不太漂亮,但这是借书人可以做到的\_(ツ)_/¯.

@ker通过创建一个未命名的临时文件对此进行了改进:

impl Recursive {
    fn back(&mut self) -> &mut Link {
        let mut anchor = &mut self.root;

        loop {
            match {anchor} {
                &mut Some(ref mut node) => anchor = &mut node.next,
                other => return other,
            }
        }
    }
}

这里的诀窍是使用{anchor} movesanchor的内容转换成一个未命名的临时文件,在该文件上执行匹配.因此,在match区块,我们不是从anchor借款,而是从临时借款,让我们可以自由修改anchor.参见相关博客文章Stuff the Identity Function Does (in Rust).

Rust相关问答推荐

基于对vec值的引用从该值中删除该值

我怎样才能从一个Rust 的日期中go 掉3年?

有没有办法模仿对象安全克隆?

下载压缩文件

从Type::new()调用函数

在0..1之间将U64转换为F64

将serde_json读入`VEC<;T&>;`( rust 色)时出现问题

不能在Rust中使用OpenGL绘制三角形

如何执行数组文字的编译时串联?

Rust 文件未编译到 dll 中

Rust 异步循环函数阻塞了其他future 任务的执行

Rust编译器通过哪些规则来确保锁被释放?

枚举的利基优化如何在 Rust 中工作?

n 个范围的笛卡尔积

判断 is_ok 后重用结果

使用 HashMap 条目时如何避免字符串键的短暂克隆?

为什么 Rust 编译器在移动不可变值时执行复制?

为什么这个闭包没有比 var 长寿?

为什么这个 Trait 无效?以及改用什么签名?

为什么这里需要类型注解?