我有一个以某种方式操作对象数组的算法,但是调用者需要能够监听由算法触发的某些事件(对象的更新)。
下面是一个简化的示例,说明我正在尝试执行的操作。(Rust playground)
这是算法模块:
// Some module containing the algorithm.
// This module doesn't want to know what the caller wants to do in the listener.
trait Listener {
fn update(&mut self, s: String);
}
struct Object<L: Listener> {
/* other stuff */
listener: L,
}
fn do_stuff<L: Listener>(objects: &mut [Object<L>]) {
// do stuff, which eventually might call the listener of each object any number of times.
objects[0].listener.update("zero".to_string());
objects[1].listener.update("one".to_string());
objects[0].listener.update("zeroes".to_string());
}
调用者将调用do_stuff()
,do_stuff()
以某种方式改变对象数组,并在改变对象时调用每个对象上的侦听器,这个算法模块不需要知道回调被触发时调用者想要做什么。
这是主要模块:
// Main module
// Obviously this can't implement Copy and Clone, because of the mut ref.
struct MyListener<'a>{
node: &'a mut Vec<String>,
prefix: &'static str,
}
impl<'a> Listener for MyListener<'a> {
fn update(&mut self, s: String) {
self.node.push(format!("{} {}", self.prefix, s));
}
}
pub fn main() {
let mut strings = Vec::new();
let mut objects = vec![
Object{listener: MyListener{node: &mut strings, prefix: "red"}},
Object{listener: MyListener{node: &mut strings, prefix: "blue"}},
Object{listener: MyListener{node: &mut strings, prefix: "green"}},
];
do_stuff(&mut objects);
}
错误:
Compiling playground v0.0.1 (/playground)
error[E0499]: cannot borrow `strings` as mutable more than once at a time
--> src/main.rs:37:43
|
35 | let mut objects = vec![
| _______________________-
36 | | Object{listener: MyListener{node: &mut strings, prefix: "red"}},
| | ------------ first mutable borrow occurs here
37 | | Object{listener: MyListener{node: &mut strings, prefix: "blue"}},
| | ^^^^^^^^^^^^ second mutable borrow occurs here
38 | | Object{listener: MyListener{node: &mut strings, prefix: "green"}},
39 | | ];
| |_____- first borrow later used here
error[E0499]: cannot borrow `strings` as mutable more than once at a time
--> src/main.rs:38:43
|
35 | let mut objects = vec![
| _______________________-
36 | | Object{listener: MyListener{node: &mut strings, prefix: "red"}},
| | ------------ first mutable borrow occurs here
37 | | Object{listener: MyListener{node: &mut strings, prefix: "blue"}},
38 | | Object{listener: MyListener{node: &mut strings, prefix: "green"}},
| | ^^^^^^^^^^^^ second mutable borrow occurs here
39 | | ];
| |_____- first borrow later used here
For more information about this error, try `rustc --explain E0499`.
error: could not compile `playground` due to 2 previous errors
在我的实际代码中,我尝试调用&mut svg::Document
上的一个可变函数,而不是更新Vec(从svg板条箱中)向文档添加一些SVG节点,该算法将对象转换为基本形状,每个侦听器获取这些基本形状和当前对象的样式(例如,线宽、颜色),并生成SVG命令并将其添加到svg::Document
。
上面的代码显然不起作用,因为我多次借用了strings
向量,但实际上没有任何方法可以将其拆分,所有这些都需要修改同一个向量。
我也可以让do_stuff返回更新列表,并让调用者稍后应用它们,但这将涉及一堆临时向量。
有没有办法让现在的设计发挥作用?
1条答案
按热度按时间mspsb9vt1#
将
strings
向量 Package 在RefCell
中,然后使用共享引用: