微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

向前和向后跳跃的迭代器多次可变地借用

如何解决向前和向后跳跃的迭代器多次可变地借用

我正在写一个虚拟机,它可以一条一条地执行指令,也可以向前和向后跳跃。

例如,如果它有一个指令列表 [A,>B,C,D] 并且当前位于指令 B。向前跳 2 将跳过 2 条指令(BC[A,B,>D]。跳回 1 应该只跳过 B [>A,D]

这就是我实现迭代器的方式

impl <'a> Iterator for VmReader<'a> {
    type Item = &'a Instruction;

    fn next(&mut self) -> Option<Self::Item> {
        if self.ip < self.chunk.code.len() {
            let instruction: &'a Instruction = &self.chunk.code[self.ip];
            self.ip += 1;
            Some(instruction)
        } else {
            None
        }
    }
}

reader 存储当前指令的索引,jump_backward(2) 将其减 2。

这是我尝试使用它的方式:

while let Some(instruction) = reader.next() {
    if instruction == &Instruction::Add {
        reader.jump_backward(2);
        continue;
    }
}

但它不起作用,因为我将 reader 可变地借用了两次:

error[E0499]: cannot borrow `reader` as mutable more than once at a time
   --> src/vmm/vm_reader.rs:99:39
    |
99  |         while let Some(instruction) = reader.next() {
    |                                       ^^^^^^
    |                                       |
    |                                       second mutable borrow occurs here
    |                                       first borrow later used here
100 |             if instruction == &Instruction::Add {
101 |                 reader.jump_backward(2);
    |                 ------ first mutable borrow occurs here

你能提出解决这个问题的方法吗?

解决方法

一个解决方案是不使用 docker-compose.yml 特征,而是使用类似迭代器的结构,该结构将包装 Iterator 游标但不包装读取器,其 ip 函数将读取器作为论证。

它看起来像这样:

next

这将是安全和干净的,但会阻止某些迭代器模式。


如果不需要将Reader和迭代分开,也可以直接将ip游标存储在Reader中。

这是第二种解决方案的示例:

#[derive(Default)]
struct VmIterator {
     ip: usize,}
impl VmIterator {
    pub fn next(&mut self,chunk: &Reader) -> Option<&Instruction> {
        if self.ip < chunk.code.len() {
            let instruction: &'a Instruction = &self.chunk.code[self.ip];
            self.ip += 1;
            Some(instruction)
        } else {
            None
        }
    }
}

请注意,虽然它仍然是一个迭代器,但如果在迭代时发生变异,借用检查器将禁止某些迭代器构造,因此显式 #[derive(Debug,Default,Clone)] struct Instruction {} struct Reader<'s> { source: &'s[Instruction],c: usize,} impl<'s> Reader<'s> { pub fn new(source: &'s[Instruction]) -> Self { Self { source,c: 0 } } pub fn decr(&mut self) { self.c -= 2; } } impl<'s> Iterator for Reader<'s> { type Item = &'s Instruction; fn next(&mut self) -> Option<Self::Item> { let c = self.c; if c < self.source.len() { self.c += 1; self.source.get(c) } else { None } } } fn main() { let instructions = vec![Instruction::default(); 10]; let mut r = Reader::new(&instructions); let mut i = 0; while let Some(c) = r.next() { if i%3 == 2 { r.decr(); } i += 1; dbg!(c); } }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。