我想在拥有这些功能的结构上应用某些功能。
第一次尝试:
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
不会与您要迭代的缓冲区混在一起。实际上,您的最终代码也存在相同的问题:op
可能会截断缓冲区,从而导致您尝试越过向量末尾时出现 panic 。
一种安全的方法是在评估时换出buffer
。假设您不打算对同一指令序列进行多次评估:
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/