Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/.htaccess/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 向前和向后跳跃的迭代器。多次易变地借款_Rust - Fatal编程技术网

Rust 向前和向后跳跃的迭代器。多次易变地借款

Rust 向前和向后跳跃的迭代器。多次易变地借款,rust,Rust,我正在编写一个虚拟机,它可以一个接一个地执行指令,还可以向前和向后跳转 例如,如果它有一个指令列表[a、>B、C、D],并且当前位于指令B。向前跳2将跳过2条指令(B和C)[A,B,C,>D]。按1向后跳应该只跳过B[>A,B,C,D] 这就是我实现迭代器的方式 impl{ 输入Item=&'a指令; fn下一步(&mut self)->选项{ 如果self.ip选项{ 如果self.ip选项{ 如果self.ip

我正在编写一个虚拟机,它可以一个接一个地执行指令,还可以向前和向后跳转

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

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

impl{
输入Item=&'a指令;
fn下一步(&mut self)->选项{
如果self.ip
读取器
存储当前指令的索引,并将其向后跳转(2)
递减2

以下是我尝试使用它的方式:

while let Some(指令)=reader.next(){
如果指令==&指令::添加{
读取器。向后跳转(2);
持续
}
}
但它不起作用,因为我不断地借用
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


您能为这个问题提出一个解决方案吗?

一个解决方案是不使用
迭代器
特性,而是使用类似迭代器的结构,该结构将封装
ip
光标,而不是读卡器,其
next
函数将读卡器作为参数

它看起来像这样:

#[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
        }
    }
}
#[派生(默认)]
结构VmIterator{
ip:usize,
}
impl虚拟迭代器{
pub fn next(&mut self,chunk:&Reader)->选项{
如果self.ip
这将是安全和干净的,但会阻止一些迭代器模式


如果不需要将读卡器和迭代分开,还可以将ip游标直接存储在读卡器中

下面是第二个解决方案的示例:

#[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);
    }
}
#[派生(调试、默认、克隆)]
结构指令{}
结构读取器{
发布fn新信息(来源:&[说明]->Self{
自{源,c:0}
}
发布fn说明(&M自我){
自我评价c-=2;
}
}
恳求{
输入项目=&的指令;
fn下一步(&mut self)->选项{
设c=self.c;
如果c

请注意,尽管它仍然是一个迭代器,但如果在迭代过程中进行了变异,则借用检查器将禁止某些迭代器构造,因此,当let some(c)=r.next()时,显式的
{

解决方案是不使用
迭代器
特性,而是使用类似迭代器的结构,该结构将封装
ip
光标,但不封装读取器,其
next
函数将读取器作为参数

它看起来像这样:

#[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
        }
    }
}
#[派生(默认)]
结构VmIterator{
ip:usize,
}
impl虚拟迭代器{
pub fn next(&mut self,chunk:&Reader)->选项{
如果self.ip
这将是安全和干净的,但会阻止一些迭代器模式


如果不需要将读卡器和迭代分开,还可以将ip游标直接存储在读卡器中

下面是第二个解决方案的示例:

#[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);
    }
}
#[派生(调试、默认、克隆)]
结构指令{}
结构读取器{
发布fn新信息(来源:&[说明]->Self{
自{源,c:0}
}
发布fn说明(&M自我){
自我评价c-=2;
}
}
恳求{
输入项目=&的指令;
fn下一步(&mut self)->选项{
设c=self.c;
如果c

请注意,尽管它仍然是一个迭代器,但如果在迭代过程中进行了变异,则借用检查器将禁止某些迭代器构造,因此,当let some(c)=r.next()时,显式的
{

将注释移动到您的答案将注释移动到您的答案谢谢!但是如果我们放弃迭代器模式,那么在封装
ip
字段的同时,它是否可以在没有迭代器的情况下实现?我问这个问题是因为这个解决方案产生了两个实体:
Reader
iterator
似乎很麻烦:)新的“迭代器”只是ip域,在内存中的位置不会比usize更大,它只是增加了类型安全性。好吧,我只是问的不是性能和优化,而是软件架构,因为现在代码库将有2个实体。你认为可以用1个实体完成吗?取决于你的用例,但没有问题如果只有一个可能的读取,则在原始结构中使用
reading\u index
。在一般情况下,分离数据和迭代会更灵活一些。但是我是否能够对