我想在拥有这些函数的结构上应用一些函数。
首先尝试:
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);
}
}
是否有更好的办法解决借阅检查工具?
答案 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
。