我想在拥有这些函数的结构上应用一些函数。
第一次尝试:
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);
}
}
是否有更好的方法来解决借用检查器?
最佳答案
您不应该真正尝试“绕过借用检查器”。它阻止您执行此操作,因为无法保证您调用的操作不会干扰您尝试迭代的缓冲区。事实上,您的最终代码也存在同样的问题:op
可能截断缓冲区,从而在您尝试读取超过向量末尾时导致 panic 。 p>
一种安全的方法是在评估缓冲区时更换它。假设您不打算多次评估相同的指令序列:
fn evaluate(&mut self) {
use std::mem;
for op in mem::replace(&mut self.buffer, vec![]) {
op(self);
}
}
在这种情况下,新的缓冲区可以由调用的op
修改,而不会干扰evaluate
。
关于iterator - 在拥有这些函数的结构上应用一些函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34564944/