在拥有这些函数的结构上应用一些函数
Apply some functions on a struct owning those functions
我想在拥有这些函数的结构上应用一些函数。
第一次尝试:
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);
}
}
有没有更好的方法来绕过借用检查器?
你真的不应该 "work around the borrow checker"。它阻止您这样做,因为不能保证您调用的 op
s 不会弄乱您试图迭代的缓冲区。事实上,你的最终代码有同样的问题:一个 op
可以 截断 缓冲区,当你试图读取超过向量的末尾时导致恐慌。
一种安全的方法是在评估时换掉 buffer
。假设您不打算多次评估相同的指令序列:
fn evaluate(&mut self) {
use std::mem;
for op in mem::replace(&mut self.buffer, vec![]) {
op(self);
}
}
在这种情况下,调用的 op
可以修改新缓冲区,而不会干扰 evaluate
。
我想在拥有这些函数的结构上应用一些函数。
第一次尝试:
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);
}
}
有没有更好的方法来绕过借用检查器?
你真的不应该 "work around the borrow checker"。它阻止您这样做,因为不能保证您调用的 op
s 不会弄乱您试图迭代的缓冲区。事实上,你的最终代码有同样的问题:一个 op
可以 截断 缓冲区,当你试图读取超过向量的末尾时导致恐慌。
一种安全的方法是在评估时换掉 buffer
。假设您不打算多次评估相同的指令序列:
fn evaluate(&mut self) {
use std::mem;
for op in mem::replace(&mut self.buffer, vec![]) {
op(self);
}
}
在这种情况下,调用的 op
可以修改新缓冲区,而不会干扰 evaluate
。