在拥有这些函数的结构上应用一些函数

时间:2016-01-02 10:38:03

标签: iterator rust lifetime

我想在拥有这些函数的结构上应用一些函数。

首先尝试:

struct VM {
    buffer: Vec<fn(&mut VM)>,
    stack: Vec<isize>,
}

impl VM {
    fn new() -> VM {
        VM {
            buffer: vec![VM::op_zero, VM::op_drop],
            stack: vec![],
        }
    }
    fn op_zero(&mut self) { self.stack.push(0); }
    fn op_drop(&mut self) {
        match self.stack.pop() {
            Some(i) => println!("drop {}", i),
            None => println!("stack underflow!")
        }
    }
    fn evaluate(&mut self) {
        for op in self.buffer {
            op(self);
        }
    }
}

fn main() {
    let mut vm = VM::new();
    vm.evaluate();
}

由于搬出借来的内容,这不起作用。我在&之前添加了self.buffer,但它仍然无效,因为self.buffer也被借用为不可变的。

fn evaluate(&mut self) {
    for op in &self.buffer {
        op(self);
    }
}

第三次尝试有效,但是有运行时边界检查数组索引的开销:

fn evaluate(&mut self) {
    let len = self.buffer.len();
    for i in 0..len {
        let op = self.buffer[i];
        op(self);
    }
}

是否有更好的办法解决借阅检查工具?

1 个答案:

答案 0 :(得分:4)

你不应该真正尝试围绕借阅检查工作&#34;。它阻止你这样做,因为你不能保证你调用的op不会弄乱你试图迭代的缓冲区。实际上,您的最终代码也存在同样的问题:op可以截断缓冲区,当您尝试读取向量的末尾时会导致混乱。

安全地执行此操作的一种方法是在评估时替换buffer。假设您不打算多次评估相同的指令序列:

fn evaluate(&mut self) {
    use std::mem;
    for op in mem::replace(&mut self.buffer, vec![]) {
        op(self);
    }
}

在这种情况下,新缓冲区可以被调用的op修改,而不会干扰evaluate